一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
Java中的Set接口及实现类
掌握:
Set接口及其实现类的特点及相关方法的用法
HashSet集合存储并遍历字符串元素:
Collection
--List
有序(存储顺序和取出顺序一致),可重复
--Set
无序(存储顺序和取出顺序不一致),唯一
HashSet:
它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
注意:
虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存储顺序,如果你的顺序恰好和它的存储顺序一致,这代表不了有序,你可以多存储一些数据,就能看到效果。
HashSet:存储字符串并遍历
问题: 为什么存储字符串的时候,字符串内容相同的只存储了一个呢?
通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode()和equals()。
步骤:
首先比较哈希值
如果相同,继续走,比较地址值或者走equals()
如果不同,就直接添加到集合中
按照方法的步骤来说:
先看hashCode()值是否相同
相同:继续走equals()方法
返回true:说明元素重复,就不添加
返回false:说明元素不重复,就添加到集合
不同:就直接把元素添加到集合
如果类没有重写这两个方法,默认使用的Object()。一般来说不相同。
而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。
HashSet<String> strings=new HashSet<String>();
strings.add("hello");
strings.add("world");
strings.add("java");
strings.add("world");
strings.add("java");
Iterator<String> iterator = strings.iterator();
System.out.println("-----迭代器---------");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("------增强for--------");
for (String s : strings) {
System.out.println(s);
}
System.out.println("------forEach--------");
strings.forEach(s->System.out.println(s));
使用HashSet集合存储自定义对象,并保证元素的唯一性:
要求:如果两个对象的成员变量值都相同,则为同一个元素。
目前是不符合我的要求的:因为我们知道HashSet底层依赖的是hashCode()和equals()方法。
而这两个方法我们在自定义类中没有重写,所以,默认使用的是Object类。
这个时候,他们的哈希值是不会一样的,根本就不会继续判断,执行了添加操作。
如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。
自动生成的快捷键:按 alt + shift + s , 然后按h
生成的代码与自己定义的类属性有关。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
TreeSet集合保证元素排序和唯一性的原理
唯一性:是根据比较的返回是否是0来决定。
排序:
A:自然排序(元素具备比较性)
让元素所属的类实现自然排序接口 Comparable
B:比较器排序(集合具备比较性)
让集合的构造方法接收一个比较器接口的子类对象 Comparator
比较器排序有三种方式
方式1:
定义一个类实现Comparator接口,将该类对象作为TreeSet构造方法的参数TreeSet<t> ts=new TreeSet<t>(new MyComparator());
方式2:
定义一个类实现Comparator接口,将该类对象作为TreeSet构造方法的参数,该类放在测试类一个文件
方式3:
在TreeSet类带参构造方法中定义一个实现Comparator接口的匿名内部类