目录
Collection集合体系
Colletion集合的三种遍历方式
方式一:迭代器
方式二:foreach(增强for循环)遍历集合。
方式三:Lambda表达式遍历集合
List系列集合
List系列集合特点
List集合特有方法
List遍历方式:
为何ArrayList查询快、增删元素相对较慢
linkedList的特点
集合的并发修改异常问题
存在的问题
原因及解决办法
1.迭代器删除集合元素
2.foreach迭代删除
3.Lambda表达式删除
4.for循环删除
Set集合体系
HashSet底层原理
哈希表详细流程
linkedHashSet集合概述和特点
TreeSet集合概述和特点
TreeSet集合默认的规则
TreeSet排序规则
自定义排序规则
Collections集合工具类
集合元素的添加和打乱
集合元素的排序
Collection集合体系
特点总结
List系列集合:添加的元素是有序、可重复、有索引。
ArrayList、LinekdList :有序、可重复、有索引。
Set系列集合:添加的元素是无序、不重复、无索引。
HashSet: 无序、不重复、无索引;linkedHashSet: 有序、不重复、无索引。
TreeSet:按照大小默认升序排序、不重复、无索引。
Colletion集合的三种遍历方式
方式一:迭代器
l
迭代器在
Java
中的代表是
Iterator
,迭代器是集合的专用遍历方式。
迭代器遍历集合。
-- 方法:
public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的
boolean hasNext():判断是否有下一个元素,有返回true ,反之。
E next():获取下一个元素值!
--流程:
1.先获取当前集合的迭代器
Iterator it = lists.iterator();
2.定义一个while循环,问一次取一次。
通过it.hasNext()询问是否有下一个元素,有就通过
it.next()取出下一个元素
public class IteratorDemo {
public static void main(String[] args) {
ArrayList arr=new ArrayList();
arr.add("门泊东吴");
arr.add("万里");
arr.add("船");
System.out.println(arr);
Iterator it=arr.iterator();
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
while(it.hasNext()){
System.out.println(it.next());
}
}
}
方式二:foreach(增强for循环)遍历集合。
foreach是一种遍历形式,可以遍历集合或者数组。
foreach遍历集合实际上是迭代器遍历集合的简化写法。
foreach遍历的关键是记住格式:
for(被遍历集合或者数组中元素的类型 变量名称 : 被遍历集合或者数组){}
public class IteratorDemo {
public static void main(String[] args) {
ArrayList arr=new ArrayList();
arr.add("门泊东吴");
arr.add("万里");
arr.add("船");
for (String s : arr) {
System.out.println(s);
}
}
}
增强for循环:既可以遍历集合也可以遍历数组
方式三:Lambda表达式遍历集合
public class IteratorDemo {
public static void main(String[] args) {
ArrayList arr=new ArrayList();
arr.add("门泊东吴");
arr.add("万里");
arr.add("船");
System.out.println(arr);
//为简化前的写法
// arr.forEach(new Consumer() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });
//Lanmda表达式简化后的写法
arr.forEach((String s) -> System.out.println(s));
//还能再简化,只不过没必要了
}
}
这三种方式我用第二种比较多,第二种一眼就知道是啥意思,好理解,第三种熟练了也很爽,但我搞不懂它内部的意思,每次都要查一下。
List系列集合
List系列集合特点
ArrayList、LinekdList :有序,可重复,有索引。
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复
List集合特有方法
List集合特有方法
List遍历方式:
(1)for循环。(独有的,因为List有索引)。
(2)迭代器。
(3)foreach。
(4)JDK 1.8之后的Lambda表达式。
为何ArrayList查询快、增删元素相对较慢
因为ArrayList底层是数组实现的,根据下标查询不需要比较,查询方式为,首地址+(元素长度*下标),基于这个位置读取相应的字节数就可以了,所以非常快;
增删会带来元素的移动,增加数据会向后移动,删除数据会向前移动,所以影响效率。
相反,在添加或删除数据的时候,linkedList只需改变节点之间的引用关系,这就是linkedList在添加和删除数据的时候通常比ArrayList要快的原因
linkedList的特点
还有入栈、压栈(push)和出栈、弹栈(pop),addfirst就是push,removefirst就是pop
public class ListDemo03 {
public static void main(String[] args) {
linkedList stack = new linkedList<>();
// 入栈 压栈 (push)
stack.push("第1颗子弹");
stack.push("第2颗子弹");
stack.push("第3颗子弹");
stack.push("第4颗子弹");
System.out.println(stack);
// 出栈 弹栈 pop
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack);
}}
//输出结果为
[第4颗子弹, 第3颗子弹, 第2颗子弹, 第1颗子弹]
第4颗子弹
第3颗子弹
第2颗子弹
[第1颗子弹]
集合的并发修改异常问题
当从集合中找出并删除某个元素的时候可能会出现的一种并发修改异常问题
存在的问题
迭代器遍历集合且直接用集合删除元素的时候可能出现。
增强
for
循环遍历集合且直接用集合删除元素的时候可能出现。
原因及解决办法
1.迭代器删除集合元素
// 需求:删除全部的Java信息。
// a、迭代器遍历删除
Iterator it = list.iterator();
while (it.hasNext()){
String ele = it.next();
if("Java".equals(ele)){
// 删除Java
// list.remove(ele); // 集合删除会出毛病
it.remove(); // 删除迭代器所在位置的元素值(没毛病)
}
1.迭代器删除集合元素
// 需求:删除全部的Java信息。
// a、迭代器遍历删除
Iterator it = list.iterator();
while (it.hasNext()){
String ele = it.next();
if("Java".equals(ele)){
// 删除Java
// list.remove(ele); // 集合删除会出毛病
it.remove(); // 删除迭代器所在位置的元素值(没毛病)
}
迭代器删除的时候不能用集合的remove方法,只能用迭代器的remov方法!
2.foreach迭代删除
// b、foreach遍历删除 (会出现问题,这种无法解决的,foreach不能边遍历边删除,会出bug)
for (String s : list) {
if("Java".equals(s)){
list.remove(s);
}
}
3.Lambda表达式删除
//c、lambda表达式(会出现问题,这种无法解决的,Lambda遍历不能边遍历边删除,会出bug)
list.forEach(s -> {
if("Java".equals(s)){
list.remove(s);
}
});
//c、lambda表达式(会出现问题,这种无法解决的,Lambda遍历不能边遍历边删除,会出bug)
list.forEach(s -> {
if("Java".equals(s)){
list.remove(s);
}
});
Lambda表达式本质上也是foreach!
4.for循环删除
// d、for循环(边遍历边删除集合没毛病,但是必须从后面开始遍历删除才不会出现漏掉应该删除的元素)
for (int i = list.size() - 1; i >= 0 ; i--) {
String ele = list.get(i);
if("Java".equals(ele)){
list.remove(ele);
}
}
for循环删除需要从后往前删除,或者从前往后但是需要做一个i--
Set集合体系
1.
Set
系列集合的特点。
无序、不重复、无索引。
2.
Set
集合的实现类特点。
l
HashSet
无序、不重复、无索引。
linkedHashSet
有序
、不重复、无索引。
TreeSet
可排序
、不重复、无索引。
Set
集合的功能上基本上与
Collection
的
API
一致。
HashSet底层原理
HashSet
集合底层采取
哈希表
存储的数据。
哈希表是一种对于增删改查数据性能都较好的结构。
JDK8
之前的,底层使用
数组
+
链表
组成
JDK8
开始后,底层采用
数组
+
链表
+
红黑树
组成。
结论:哈希表是一种对于增删改查数据性能都较好的结构。
l
当挂在元素下面的数据过多时,查询性能降低,从
JDK8
开始后,当链表长度超过
8
的时候,自动转换为红黑树。
哈希表详细流程 ① 创建一个默认长度 16 ,默认加载因为 0.75 的数组,数组名 table ② 根据元素的哈希值跟数组的长度计算出应存入的位置 ③ 判断当前位置是否为 null ,如果是 null 直接存入,如果位置不为 null ,表示有元素, 则调用 equals 方法比较属性值,如果一样,则不存,如果不一样,则存入数组。 ④ 当数组存满到 16*0.75=12 时,就自动扩容,每次扩容原先的两倍
结论:如果希望Set集合认为2个内容一样的对象是重复的,必须重写对象的hashCode()和equals()方法
linkedHashSet集合概述和特点
l
有序
、不重复、无索引。
l
这里的有序指的是保证存储和取出的元素顺序一致
l
原理
:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
TreeSet集合概述和特点
l
不重复、无索引、可排序
l
可排序:按照元素的大小默认升序(有小到大)排序。
l
TreeSet
集合底层是基于
红黑树的数据结构
实现排序的,增删改查性能都较好。
l
注意:
TreeSet
集合是一定要排序的,可以将元素按照指定的规则进行排序。
TreeSet集合默认的规则
l
对于数值类型:
Integer , Double
,官方默认按照大小进行升序排序。
l
对于字符串类型:默认按照首字符的编号升序排序。
l
对于自定义类型如
Student
对象,
TreeSet
无法直接排序。
TreeSet集合默认的规则 l 对于数值类型: Integer , Double ,官方默认按照大小进行升序排序。 l 对于字符串类型:默认按照首字符的编号升序排序。 l 对于自定义类型如 Student 对象, TreeSet 无法直接排序。
结论:想要使用TreeSet存储自定义类型,需要制定排序规则
TreeSet排序规则
l
对于数值类型:
Integer , Double
,官方默认按照大小进行升序排序。
l
对于字符串类型:默认按照首字符的编号升序排序。
l
对于自定义类型如
Student
对象,
TreeSet
无法直接排序。
结论:想要使用
TreeSet
存储自定义类型,需要制定排序规则
自定义排序规则
TreeSet
集合存储对象的的时候有
2
种方式可以设计自定义比较规则
方式一
让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
注意!是在对应的类实现接口,而且接口后面要加上<类型>
方式二
TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。
Set apples = new TreeSet<>(new Comparator() {
@Override
public int compare(Apple o1, Apple o2) {
// return o1.getWeight() - o2.getWeight(); // 升序
// return o2.getWeight() - o1.getWeight(); // 降序
// 注意:浮点型建议直接使用Double.compare进行比较
// return Double.compare(o1.getPrice() , o2.getPrice()); // 升序
return Double.compare(o2.getPrice() , o1.getPrice()); // 降序
}
});
Collections集合工具类
集合元素的添加和打乱
集合元素的排序
看清楚啦,只能对List集合排序
List和TreeSet都能自定义排序,自己定义比较规则,TreeSet用的是集合自带比较器,用匿名内部类的方式重写比较规则,所以在创建TreeSet对象时就已经可以重写比较规则了。而List用的是Collection的sort方法自带的比较器对象。
Map集合体系使用最多的Map集合是HashMap。
重点掌握HashMap , linkedHashMap , TreeMap。其他的后续理解
Map集合体系特点
Map集合的特点都是由键决定的。 Map集合的键是无序,不重复的,无索引的 , 值 不做要求(可以重复)。 Map集合后面重复的键对应的 值 会覆盖前面 重复键的值 。Map集合的键值对都可以为null。
Map集合实现类特点
HashMap:元素按照键是无序,不重复,无索引,值不做要求。 ( 与 Map 体系一致 ) linkedHashMap:元素按照键是 有序 ,不重复,无索引,值不做要求。 TreeMap :元素按照建是 排序 ,不重复,无索引的, 值不做要求。 Map集合的遍历方式一 方式一 : 键找值的方式遍历:先获取Map集合全部的键,再根据遍历键找值。 方式二: 键值对的方式遍历 ,把“键值对“看成一个整体, 难度较大。方式三:JDK 1.8开始之后的新技术:Lambda表达式



