概述
之前学的ArrayList就是集合的一种,是一种容器,可以往里面存东西,大小可变
Collection集合体系
Collection的常用方法
以后Collection体系的集合都可以用下图的方法
注意
toArray方法的数组类型是Object,这样就可以接收任意类型的数据到数组中去,如果需要指定数组类型,方法如下图
补充
addAll( ) 方法,可以将一个集合中的数据拷贝一份到另一个集合中去,示例如下图
输出结果===>
Collection的遍历方式
之后所有的Collection体系集合都能使用这些方法,而之前用的for方法本质是利用 i 充当索引进行遍历的,而Set系列集合是没有索引的,只能在List系列集合中使用
迭代器
(是不是有点像链表的遍历🤔,不准确理解方式:next指向当前所在元素,获取后就指向下一个元素,使用hasnext判断指向元素是否为空)
示例:
增强for循环
示例:ele可以取任何名字,把ele理解成当前指向的元素,他会遍历完所有的元素
Lambda表达式
Java提供一个foreach方法用于遍历,可以采用lambda表达式简化,目前还看不出其强大的简化能力,当后面学到对map集合遍历时,才能感受到他的强大之处
List集合
未来创建ArrayList或LinkList推荐采用多态的写法:List<类型> 类名 = new ArrayList<>( ); 或 List<类型> 类名 = new LinkedList<>( );
ArrrayList与LinkedList的底层实现不同,采用的数据结构不一样,适用场景不同
List特有方法
List遍历方式
有索引,因此是支持普通的for循环的
ArrayList
底层原理
应用场景
ArrayList 适用于根据索引查数据、或数据量不大时;不适用于数据量大且需要频繁进行增删操作的场景
LinkedList
底层原理
应用场景
Set集合
HashSet用的比较多
前置知识-哈希值
每个对象都有一个哈希值,可以通过哈希值找到对象,若出现相同的哈希值-->碰撞(类比数据结构中的哈希查找)
哈希碰撞:
String类的hashCode()方法把字符值代入特定公式计算哈希值,知道公式就能轻易设计出哈希碰撞
上图的例子是故意设计的,是为了演示哈希碰撞,实际中并不会这么容易就撞
HashSet
无序、不重复、无索引
jdk8之前:采用的是哈希表,因此增删改查效率都不错
补充知识
- 数组长度 × 加载因子 = 需要扩容的大小。比如上图,16×0.75=12,当数组中占了12个位置的时候,就会进行扩容,增加数组长度至原来长度的两倍
- 从jdk8开始,当链表的长度>8,且数组长度>=64,自动将链表转换成红黑树(具体红黑树细节看408笔记)
去重机制
HashSet默认不能对内容一样的两个不同对象进行去重!因为虽然内容一样,但是地址是不同的,因此HashSet会认为两个对象并不是重复的
解决办法:在对象的类中重写 equals方法 与 HashCode方法 即可,直接右键generate可以生成,具体如下,简单的理解 ---> 重写后的equals方法:若对象相同会返回true,而重写后的hashcode方法:若两个对象的内容一样就返回相同的哈希值
LinkedHashSet
有序、不重复、无索引
如何实现有序?双链表实现,但也因此增加了内存
TreeSet
不重复、无索引、可排序
自定义排序规则
由于无法进行排序,因此需要自己指定排序规则,如下图,之前在学习Arrays.sort时学过,这里方法一样
补充:
- 如果两种方法都是用了,TreeSet会采用就近原则使用外部重写的Comparator规则,而不使用对象类内部重新的
- 如果两个对象中出现的某一项相同,比如采用年龄排序,年龄都是16,则会丢失其中一个,因为Set的规则就是出现输入相同的数据时会保留先前输入的
Comparable
让需要排序的对象类实现Comparable泛型接口,重写comparetor,自己指定规则,就能对对象进行排序了,示例如下:
Comparator
Comparator是一个匿名内部类,在传入参数时直接重写,可以利用TreeSet的有参构造器直接设置Comparator对象
示例如下,其中调用的 Double.compare(double a,double b) 方法:a>b return 1 ; a<b return -1; a==b return0
各种集合的使用总结
注意事项
集合的并发修改异常问题
下面这段代码就会发生并发修改异常问题,主要问题在于remove,remove后集合整体是会往前移一个的,因此当找到含李的名字的时候,remove后集合会整体往前移,此时hasNext会让指针指向下一个,导致漏检
解决办法
若采用迭代器遍历,不要直接使用 集合.remove,而是采用 迭代器.remove,就可以解决该问题
注意:若使用增强for循环或是lambda表达式进行循环出现并发修改异常问题,是没有办法解决的
其他相关知识
可变参数
示例:
Collections
addAll 示例:
shuffle 示例:
sort :
默认升序排序,如果里面存的是对象,就需要像上面一样使用 comparable 或者 comparator 设置比较规则进行排序