基本数据类型
byte
-128 - 127
1字节(8bit位)
short
-2^15 - 2^15 - 1
2字节
int
-2^31 - 2^31 - 1
4字节
long
-2^63 - 2^63 - 1
8字节
定义时需要在尾部加L或l
long num = 123L;
long num = 123l;
如果没加L并且数字没有超过int型长度,那么就会以int型展示
float
-3.403E38 - 3.403E38
4字节
精度精确到7位
定义时需要在尾部加F或f
float num = 123F;
float num = 123f;
double
-1.798E308 - 1.798E308
8字节
精度精确到14位
char
1字符占两个字节
使用单引号声明
内部只能写一个字符
不能定义空字符
可以定义ASCII值
boolean
类型转换
类型自动提升
byte、char、short--->int--->long--->float--->double
当byte、char、short三种类型变量做运算时,结果为int类型
强制转换
(int) (long) (double) (float)
不能对String的数字使用(int)进行转换
大容量类型转换小容量类型时会导致精度丢失
引用数据类型
class、interface、String
数组
多个相同数据类型按一定顺序排列的集合,并使用一个名字命名,数组是有序排列的
数组的长度,长度一旦确定就不能修改
顺序表的一种,插入元素的效率不高
数组的元素可以是基本数据类型,也可以是引用数据类型
一维数组
声明
静态初始化
数组的初始化和数组元素的初始化同时进行
int[] ids = new int[]{1001, 1002, 1003 ,1004};
// 类型推断,声明且初始化时才可以使用,声明和初始化分开处理时,不能这么做
int[] ids = {1001, 1002, 1003 ,1004};
动态初始化
数组的初始化和数组元素的初始化分开进行
// 声明数组有5个元素
String[] names = new String[5];
String names[] = new String[5];
调用数组的指定位置的元素
names[0] = "123";
names[1] = "456";
获取数组的长度
int namesLen = names.length;
遍历数组
for (int i = 0; i < namesLen; i++) {
System.out.println(names[i]);
}
数组元素的默认初始化值
声明元素后,未设置数组元素,这时访问数组的元素,会有一个初始化值
数组元素为整型时,默认初始化值为0
数组元素为浮点型时,默认初始化值为0.0
数组元素为char型时,默认初始化值为0或''
数组元素为boolean型时,默认初始化值为false
数组元素为String型时,默认初始化值为null
内存解析
堆
存储new出来的对象【对象、数组】;生成数组长度的连续内存空间,首位地址(16进制地址)
栈
存储局部变量;存储数组的变量名和数组元素在堆中的16进制地址
二维数组
声明
静态初始化
int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}};
int[][] arr1 = {{1, 2, 3}, {4, 5}};
动态初始化
String[][] arr2 = new String[5][2];
String[][] arr3 = new String[5][];
String arr4[][] = new String[5][];
String[] arr5[] = new String[5][];
调用数组的指定位置的元素
// 如果二维数组是动态初始化的,但是第二维的元素没有定义长度,这时调用将报错(空指针)
arr2[0][2] = "111";
获取数组的长度
int arr2Len = arr2.length;
int arr2FirstLen = arr2[0].length;
遍历数组
for (int i = 0; i < arr2Len; i++) {
int arr2YLen = arr2[i].length;
for (int j = 0; j < arr2YLen; j++) {
System.out.println(arr2[i][j]);
}
}
数组元素的默认初始化值
二维数组地址值: [[@15db9742
外层元素:地址值 [@15db9742
内层元素
与一维数组一致
内存解析
堆
生成数组长度的连续内存空间,首位地址(16进制地址),二维数组的元素在开辟一个内存空间,这个元素对比这个内存空间的首位地址
栈
存储数组的变量名和数组元素在堆中的16进制地址
数组复制
int[] arr1 = new int[2]{1, 2};
// 浅拷贝,这时两个数组共享同一个内存地址,当其中一个数组的元素发生变化时,另一个数组也会发生变化
arr2 = arr1;
数组工具类Arrays
import java.util.Arrays
// 比较两个数组是否相等
boolean res = Arrays.equals(int[] a, int[] b)
// 输出数组信息,如果是多维数组将展示地址值
String res = Arrays.toString(int[] a)
// 将指定值填充到数组中
Arrays.fill(int[] a, int val)
// 数组排序
Arrays.sort(int a)
// 对排序后的数组进行二分法检索指定的值,得到索引值,负数表示没找到
int index = Arrays.binarySeatch(int[] a, int key)
常见异常
// 数组角标越界异常
ArrayIndexOutBoundsException
// 空指针异常,数组元素为null时,对这个元素做方法处理时,会触发空指针
NullPointerException:
打印
char[] arr1 = new char[]{'a', 'b', 'c'};
// char型数组打印时打印的是数组元素
System.out.println(arr1);
int[] arr = new int[]{1, 2, 3};
// 其他数据类型型数组打印时打印的是地址值
System.out.println(arr);
弊端
数组一旦初始化,其长度就不可变了。
数组中存储数据特点的单一性。对于无序的、不可重复的场景的多个数据就无能为力了
数组中可用的方法、属性都极少。
针对于数组中元素的删除、插入操作性能较差
ArrayList类
是一个可变容量的数组,底层基于数组实现容量大小动态可变
扩容机制
首先扩容为原始容量的 1.5 倍。如果1.5倍太小的话,则将我们所需的容量大小赋值给 newCapacity;
如果1.5倍太大或者我们需要的容量太大,那就直接拿 newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE 来扩容。
扩容之后是通过数组的拷贝来确保元素的准确性的,所以尽可能减少扩容操作。
ArrayList 的最大存储能力:Integer.MAX_VALUE。
size为集合中存储的元素的个数。
elementData.length 为数组长度,表示最多可以存储多少个元素
数组容量
默认容量为10,使用无参构造器时是在第一次添加元素是初始化容量为10的
add、addAll操作都是先对集合容量检查 ,以确保不会数组越界。然后通过 System.arraycopy() 方法将旧数组元素拷贝至一个新的数组中去。
remove操作,首先会检查 index 是否合法,然后再判断要删除的元素是否位于数组的最后一个位置。
如果 index 不是最后一个,就再次调用 System.arraycopy() 方法拷贝数组;如果 index 是最后一个元素那么就直接将数组的最后一个位置空,size - 1即可
方法
import java.util.ArrayList;
// 定义
// E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型
ArrayList<E> objectName =new ArrayList<>();
// 支持类型
ArrayList<Boolean>
ArrayList<Byte>
ArrayList<Integer>
ArrayList<Long>
ArrayList<Float>
ArrayList<Double>
ArrayList<Character>
ArrayList<BigInteger>
ArrayList<BigDecimal>
// 向数组中添加元素
objectName.add("值1");
// 添加集合中的所有元素到数组中
objectName.addAll()
// 从数组中移除索引为0的元素
objectName.remove(0);
// 清空数组
objectName.removeAll()
// 获取数组的大小
objectName.size()
// 获取数组中指定索引的
objectName.get(index)
// 获取元素在数组中的索引值
objectName.indexOf(value)
// 判断元素是否在数组中
objectName.contains(value)
// 遍历元素
objectName.forEach()
例:
object.forEach((e) -> {
System.out.println(e);
})
排序
import java.util.Collections;
// 字母排序
Collections.sort(objectName);
// 数字排序
Collections.sort(objectName);
LinkedList类
元素插入效率比数组更高
实现了List接口和Queue接口,也就是它既可以看作是一个顺序容器,又可以看作是一个队列,同时又可以看作是一个栈
使用
import java.util.LinkedList;
// 初始化
List<String> list1 = new LinkedList<>();
List<String> list2 = new LinkedList<>(
Arrays.asList(new String[]{"a", "b", "c"}
);
List<String> list3 = new LinkedList<>(){
{
add("china");
add("english");
}
};
// 在链表后添加一个元素,如果成功,返回true,否则返回false;
list1.add(value)
// 在指定位置插入一个元素。
list1.add(value, index)
// 在链表头部插入一个元素;
list1.addFirst(value)
list1.push(value)
// 在链表尾部添加一个元素;
list1.addLast(value)
list1.offer(value)
// 移除链表中第一个元素
list1.remove()
list1.removeFirst()
list1.pop()
// 移除链表中指定的元素;
list1.remove(index)
// 查询并移除第一个元素
list1.poll()
// 移除链表中最后一个元素
list1.removeLast()
// 获取指定索引的元素
list1.get(index)
// 获取第一个元素
list1.getFirst()
// 获取最后一个元素
list1.getLast()
// 获取第一个元素,但是不移除
list1.peek()
list1.peekFirst()
// 获取最后一个元素,但是不移除
list1.peekLast()