HashSet集合底层原理
底层基于哈希表实现
JDK8以前:哈希表 = 数组 + 链表 JDK8以后:哈希表 = 数组 + 链表 + 红黑树 JDK8以前
我们发现往HashSet集合中存储元素时,底层调用了元素的两个方法:一个是hashCode方法获取元素的hashCode值(哈希值);另一个是调用了元素的equals方法,用来比较新添加的元素和集合中已有的元素是否相同。 只有新添加元素的hashCode值和集合中以后元素的hashCode值相同、新添加的元素调用equals方法和集合中已有元素比较结果为true, 才认为元素重复。 如果hashCode值相同,equals比较不同,则以链表的形式连接在数组的同一个索引为位置(如上图所示) JDK8以后
HashSet去重原理
前提条件:在一个自定义类中如何实现去重呢? 我们知道HashSet用 hashcoded() 和 equals 方法来存储元素,如果我们重写这两个方法,让这两个方法依赖于自定义类的属性,如果两个实例的属性相等,那么就会被视为两个重复的实例,那么HashSet在存储的时候,就不会重复存入。
public class Student {
private String name;
private int age;
private double height;
public Student ( ) { }
public Student ( String name, int age, double height) {
this . name= name;
this . age= age;
this . height= height;
}
@Override
public boolean equals ( Object o) {
if ( this == o) return true ;
if ( o == null || getClass ( ) != o. getClass ( ) ) return false ;
Student student = ( Student ) o;
if ( age != student. age) return false ;
if ( Double . compare ( student. height, height) != 0 ) return false ;
return name != null ? name. equals ( student. name) : student. name == null ;
}
@Override
public int hashCode ( ) {
int result;
long temp;
result = name != null ? name. hashCode ( ) : 0 ;
result = 31 * result + age;
temp = Double . doubleToLongBits ( height) ;
result = 31 * result + ( int ) ( temp ^ ( temp >>> 32 ) ) ;
return result;
}
}
LinkedHashSet底层原理
底层基于哈希表实现的(数组 链表 红黑树) 但是存在双链表机制 每次添加元素,就和上一个元素用双向链表连接一下。第一个添加的元素是双向链表的头节点,最后一个添加的元素是双向链表的尾节点。 TreeSet集合
是一个基于红黑树的有序集合。 特点:可以对元素进行排序,但是必须指定元素的排序规则,即它可以按照元素的自然顺序或者通过提供的 Comparator 进行排序。 如果往集合中存储String类型的元素,或者Integer类型的元素,它们本身就具备排序规则,所以直接就可以排序。 如果往TreeSet集合中存储自定义类型的元素,比如说Student类型,则需要我们自己指定排序规则,否则会出现异常。此时运行代码,会直接报错。原因是TreeSet不知道按照什么条件对Student对象来排序。 我们想要告诉TreeSet集合按照指定的规则排序,有两种办法:
第一种:让元素的类实现Comparable接口,重写compareTo方法 第二种:在创建TreeSet集合时,通过构造方法传递Compartor比较器对象 并发修改异常
在使用迭代器遍历集合时,可能存在并发修改异常。 迭代器遍历机制,规定迭代器遍历集合的同时,不允许集合自己去增删元素,否则就会出现这个异常。 怎么解决这个问题呢?不使用集合的删除方法,而是使用迭代器的删除方法
Iterator < String > it = list. iterator ( ) ;
while ( it. hasNext ( ) ) {
String name = it. next ( ) ;
if ( name. contains ( "李" ) ) {
list. remove ( name) ;
}
}
System . out. println ( list) ;
正确答案:
Iterator < String > it = list. iterator ( ) ;
while ( it. hasNext ( ) ) {
String name = it. next ( ) ;
if ( name. contains ( "李" ) ) {
it. remove ( ) ;
}
}
System . out. println ( list) ;
Map集合
遍历方式:
先获取map集合全部的键集合,然后遍历键来找值 获取map集合的entry对象集合,然后遍历这个集合来获得key value 方法:forEach(BiConsumer <K,V> action),结合lambda遍历Map集合
Set < String > keys = map. keySet ( ) ;
for ( String key : keys) {
double value = map. get ( key) ;
System . out. println ( key + "=====>" + value) ;
}
Set < Map. Entry < String , Double > > entries = map. entrySet ( ) ;
for ( Map. Entry < String , Double > entry : entries) {
String key = entry. getKey ( ) ;
double value = entry. getValue ( ) ;
System . out. println ( key + "---->" + value) ;
}
map. forEach ( new BiConsumer < String , Double > ( ) {
@Override
public void accept ( String k, Double v) {
System . out. println ( k + "---->" + v) ;
}
} ) ;
map. forEach ( ( k, v) -> {
System . out. println ( k + "---->" + v) ;
} ) ;
}