LinkedHashSet的底层原理
1、LinkedHashSet:
有序(添加元素的顺序和获取元素的顺序是一致的),不重复,无索引。
*依然是基于哈希表(数组,链表,红黑树)实现的
*但是,他的每个元素都额外多了一个双链表的机制来记录他前后元素的位置.
TreeSet集合
1、TreeSet集合的特点:
①不重复,无索引,排序(默认是按从小到大的顺序排列的)
②底层是基于红黑树实现的排序
注意:
对于数值类型Integer、Doublle默认按照数值本身的大小进行升序排序。
对于字符串类型,默认按照首字母的编号进行升序排序。
对于自定义类型,如Student对象,TreeSet默认是无法直接排序的。
2、自定义排序规则
*TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持以下两种方式来指定排序规则。
方式一:
*让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则.
方法二:
通过调用TreeSet集合的有参构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)
public TreeSet(Comparator<? super E>comparator)
两种方式中,关于返回值的规则:
如果认为第一个元素>第二个元素,返回正整数即可,如果认为第一个元素<第二个元素,返回负整数即可,如果认为第一个元素=第二个元素,返回0即可,此时TreeSet集合只会保留一个元素,认为两者重复。
注意:
如果类本身有实现Comparable接口,TreeSet集合同时也自带比较器,默认使用集合自带的比较器排序。
Collection系列集合的总结
1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
*用ArrayList集合,有序,可重复,有索引,底层是基于数组的(常用)
2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?
*用LinkedList集合(有序、可重复、有索引),底层是基于双链表实现的。
3、如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
*用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)
4、如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
用LinkedHashSet集合(有序,不重复,无索引),底层是基于哈希表和双链表。
5、如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
*用TreeSet集合,基于红黑树实现
集合的并发修改异常
**使用迭代器删除集合时,又同时删除集合中的数据,程序就会出现并发修改异常的错误
**由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现异常的错误。
怎么保证遍历集合同时删除数据时不出现bug?
①使用迭代器遍历集合,但用迭代器自己的删除方法删除数据即可
②如果能用for循环遍历时,可以倒着遍历并删除,或者从前往后遍历,但删除元素后做i--的操作。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class problem {
public static void main(String[] args) {
List<String> names=new ArrayList<>();
names.add("张若昀");
names.add("任素汐");
names.add("张三丰");
names.add("张智林");
names.add("郑合惠子");
System.out.println(names);
//找出集合中全部带“李”的名字,并删除
/*
Iterator<String>it= names.iterator();
while (it.hasNext()){
String name=it.next();
if (name.contains("张")){
names.remove(name);
}
}
System.out.println(names);
//使用for循环
for (int i = 0; i < names.size(); i++) {
String name=names.get(i);
if (name.contains("张")){
names.remove(name);
}
}
System.out.println(names);
*/
for (int i = 0; i < names.size(); i++) {
String name=names.get(i);
if (name.contains("张")){
names.remove(name);
i--;
}
}
System.out.println(names);
Iterator<String>it= names.iterator();
while (it.hasNext()){
String name=it.next();
if (name.contains("张")){
//names.remove(name);会出现并发修改异常的错误
it.remove();//删除迭代器当前遍历到的数据,每删除一个数据后,相当于也在底层做了i--;
}
}
System.out.println(names);
}
}