目录
1. 数组
1.1 初始化
1.2 遍历
1.3 数组执行原理
1.4 Arrays操作数组
2. String字符串
3. 集合
3.1 Collection
3.1.1 常用方法
3.1.2 分类
3.1.3 遍历方式
3.1.4 List
3.1.5 Set
3.1.6 适用场景
3.1.7 Collection总结
3.2 Collection其他操作
3.2.1 并发修改异常
3.2.2 可变参数
3.2.3 Collections工具类
一种数据结构,特点是不可变,有索引,有序。
JAVA是把编译后的字节码加载到Java虚拟机中执行的。
为了方便虚拟机执行程序,将虚拟机划分为方法区、堆、栈、本地方法栈、寄存器五块区域。重点关注方法区、堆、栈。
JAVA定义了Arrays工具类来操作数组。常用方法有:
表示字符串类型,属于引用类型,不属于基本类型。
双括号括起来的字符串,是不可变的,会存储在方法区的常量池中。
但new出来的String存储在堆中,且分配不同地址。
常用方法
大框架分为单列集合Collection和双列集合Map。
List元素有序,可重复,有索引。
Set元素无序,不可重复,无索引。
Map是无序,无索引的键值对。
List:元素有序,可重复,有索引
Set:元素无序,不重复,无索引
ArrayList底层原理: 基于数组结构实现。
数组长度固定,ArrayList可变原理:
数组扩容并不是在原数组上扩容,而是创建一个新的数组,将原来数组内容复制过去。
遍历方式:可以使用普通For循环,外加上面三种方式。
Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只 是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素。
(1)HashSet
底层原理:HashSet底层时基于Hash表实现的。
所以说要想使用HashSet存储元素,此元素对象要有两个方法:一个是hashCode方法获取元素的hashCode值(哈希值);另一个是调用了元素的equals方法,用来比较新添加的元素和集合中已有的元素是否相同。
只有新添加元素的hashCode值和集合中以后元素的hashCode值相同、新添加的元素调用equals方法和集合中已有元素比较结果为true, 才认为元素重复。
如果hashCode值相同,equals比较不同,则以链表的形式连接在数组的同一个索引为位置(如上图所示)
在JDK8开始后,为了提高性能,当链表的长度超过8时,就会把链表转换为红黑树,如下图所示:
(2)LinkedHashSet
底层原理:也是Hash表,多了双向链表来维护元素的存取顺序。
(3)TreeSet
底层原理:二叉树(红黑树数据结构)
有序,不重复,无索引。
排序时必须指定规则,tring类型的元素,或者Integer类型的元素,它们本身就具备排序规。
两种方式定义排序规则:
@Override
public int compareTo(Student o) {
//this:表示将要添加进去的Student对象
//o: 表示集合中已有的Student对象
return this.age-o.age;
}
Set set = new TreeSet<>(((o1, o2) -> o1.getAge()- o2.getAge()));
在使用迭代器遍历集合时,可能存在并发修改异常。
List list = new ArrayList<>();
list.add("王麻子");
list.add("小李子");
list.add("李爱花");
list.add("张全蛋");
list.add("晓李");
list.add("李玉刚");
System.out.println(list); // [王麻子, 小李子, 李爱花, 张全蛋, 晓李, 李玉刚]
//需求:找出集合中带"李"字的姓名,并从集合中删除
Iterator it = list.iterator();
while(it.hasNext()){
String name = it.next();
if(name.contains("李")){
list.remove(name);
}
}
System.out.println(list);
运行上面的代码,会出现下面的异常。这就是并发修改异常
为什么会出现这个异常呢?那是因为迭代器遍历机制,规定迭代器遍历集合的同时,不允许集合自己去增删元素,否则就会出现这个异常。
怎么解决?交给迭代器就行
//需求:找出集合中带"李"字的姓名,并从集合中删除
Iterator it = list.iterator();
while(it.hasNext()){
String name = it.next();
if(name.contains("李")){
//list.remove(name);
it.remove(); //当前迭代器指向谁,就删除谁
}
}
可变参数是一种特殊的形式参数,定义在方法、构造器的形参列表处,它可以让方法接收多个同类型的实际参数。
可变参数在方法内部,本质上是一个数组
public class ParamTest{
public static void main(String[] args){
//不传递参数,下面的nums长度则为0, 打印元素是[]
test();
//传递3个参数,下面的nums长度为3,打印元素是[10, 20, 30]
test(10,20,30);
//传递一个数组,下面数组长度为4,打印元素是[10,20,30,40]
int[] arr = new int[]{10,20,30,40}
test(arr);
}
public static void test(int...nums){
//可变参数在方法内部,本质上是一个数组
System.out.println(nums.length);
System.out.println(Arrays.toString(nums));
System.out.println("----------------");
}
}
注意:
一个形参列表中,只能有一个可变参数;否则会报错
一个形参列表中如果多个参数,可变参数需要写在最后;否则会报错