Set接口:
1、Set的实现类们:HashSet、TreeSet、LinkedHashSet
2、Set系列的集合的元素是不能重复的。
HashSet和LinkedHashSet:
①先比较hash值,如果hash值不一样,说明一定不相同,
②如果hash值一样,再调用equals方法比较
TreeSet:
按照元素的大小来决定是否相同元素。
3、Set接口没有增加方法,都是从Collection接口中继承的。
HashSet
元素无序
@Test
public void test1(){//不可重复
HashSet set = new HashSet();
set.add("张三");
set.add("张三");
set.add("李四");
System.out.println("不可重复"+set);//不可重复[李四, 张三]
}
@Test
public void test4(){ //HashSet无序
HashSet set = new HashSet();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("王二");
System.out.println("HashSet无序"+set);//HashSet无序[李四, 张三, 王五, 王二]
}
LinkedHashSet
元素顺序为添加顺序
LinkedHashSet是HashSet的子类,比HashSet多维护了添加的顺序。
当想要实现集合的元素的不可重复性,又想要保证元素的添加顺序,就选择使用LinkedHashSet。否则就用List系列或HashSet。
LinkedHashSet干的事多了,效率低了。
@Test
public void test1(){//不可重复
LinkedHashSet set= new LinkedHashSet();
set.add("张三");
set.add("张三");
set.add("李四");
System.out.println("不可重复"+set);//不可重复[张三, 李四]
}
@Test
public void test4(){ //LinkedHashSet元素为添加顺序
LinkedHashSet set= new LinkedHashSet();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("王二");
System.out.println("LinkedHashSet添加顺序"+set);//LinkedHashSet添加顺序[张三, 李四, 王五, 王二]
}
TreeSet
元素顺序为大小顺序
当需要元素不可重复,又要给元素排大小时(对象的大小比较),就用TreeSet。
所以要用到TreeSet,一定要用java.lang.Comparable或java.util.Comparator。
@Test
public void test1(){//不可重复
TreeSet set= new TreeSet();
set.add("张三");
set.add("张三");
set.add("李四");
System.out.println("不可重复"+set);//不可重复[张三, 李四]
}
@Test
public void test9(){
TreeSet set = new TreeSet();
//这里因为Object类型没有实现了java.lang.Comparable接口,所以不可以添加到TreeSet中
set.add(new Object());//出现异常
}
@Test
public void test4(){ //TreeSet元素顺序为大小顺序
TreeSet set= new TreeSet();
//这里因为String类型实现了java.lang.Comparable接口,所以可以添加到TreeSet中
set.add("B");
set.add("A");
set.add("C");
set.add("Z");
System.out.println("TreeSet添加顺序"+set);//TreeSet添加顺序[A, B, C, Z]
}
具体使用:
@Test
public void test10(){
//用匿名内部类实现了Comparator接口
TreeSet set = new TreeSet(new Comparator(){
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return s1.getId() - s2.getId();
}});
set.add(new Student(6,"张三"));
set.add(new Student(1,"李四"));
set.add(new Student(2,"王五"));
System.out.println(set);//[Student [id=1, name=李四], Student [id=2, name=王五], Student [id=6, name=张三]]
}
class Student{
private int id;
private String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Set系列集合的底层实现
Set的底层实现是什么?
1、HashSet : HashMap
2、TreeSet : TreeMap
3、LinkedHashSet: LinkedHashMap
Set添加元素时用add(元素),而Map添加元素put(key,value)。
添加到Set中的元素,是作为底层的Map的key,那么value它们选用了一个Object类型的常量对象PRESENT。
所有的HashSet共用同一个PRESENT对象。
所有的TreeSet共用同一个PRESENT对象。
所有的LinkedHashSet共用同一个PRESENT对象。
源码:
//new HashSet();
public HashSet() {
map = new HashMap<>();
}
//new TreeSet();
public TreeSet() {
this(new TreeMap<E,Object>());
}
//new LinkedHashSet();
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}