HashSet
首先HashSet是在Set中使用得最多的。
特点
不能保证元素的排列顺序
HashSet不是同步的,多线程同时进行修改的话,需要通过代码保证其同步
集合元素可以为null
判断两个元素相同的条件
当两个对象equals() 和 hashCode() 这两个方法返回值相等时,这代表这两个对象相等。
相应代码如下:
package HashSet;
import java.util.HashSet;
class A{
public boolean equals(Object obj){
return true;
}
}
class B{
public int hashCode(){
return 1;
}
}
class C{
public boolean equals(Object obj){
return true;
}
public int hashCode(){
return 2;
}
}
/**
* HashSet是set集合中用得最多的
* HashSet集合里面不能存放相同值,HashSet是判断两个对象相等,第一需要equals()返回值相等,而且两个对象的hashCode()方法返回值也相等
* 两个A都可以加入因为他们equals()不相等,两个C都可以加入,因为他们hashCode()不相等
*/
public class HashSetTest {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
hashSet.add(new A());
hashSet.add(new A());
hashSet.add(new B());
hashSet.add(new B());
hashSet.add(new C());
hashSet.add(new C());
System.out.println(hashSet);
}
}
结果如下:
使用规范:当两个对象通过equals()方法返回true时,这两个对象的hashCode()方法也应该返回相同的值
如果equals()返回值为true,hashCode()返回值不同时,会把这两个对象保存到Hash表不同的位置上,但是这与set的规则冲突。
如果equals()返回值不同,hashCode()返回值相同时,这时候会把它们保存在同一个位置,但是存在多个,会用链式结构进行保存。这会导致性能下降。
向HashSet中,添加一个可变对象后,后面程序进行修改该可变对象的实例变量,则可能导致它与该集合其他元素相同,可能导致HashSet中有两个相同的元素
测试代码如下:
package HashSet;
import java.util.HashSet;
import java.util.Iterator;
class R{
int count;
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(obj != null && obj.getClass() == R.class){
return ((R) obj).count == this.count;
}
return false;
}
public int hashCode(){
return this.count;
}
@Override
public String toString() {
return "R{" +
"count=" + count +
'}';
}
public R(int count) {
this.count = count;
}
}
public class HashSetTest2 {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
hashSet.add(new R(5));
hashSet.add(new R(-3));
hashSet.add(new R(9));
hashSet.add(new R(-2));
System.out.println(hashSet);
//取出第一个元素
Iterator iterator = hashSet.iterator();
R first = (R)iterator.next();
first.count = -3;
//集合中有重复的元素
System.out.println(hashSet);
//删除count为-3的元素
hashSet.remove(new R(-3));
System.out.println(hashSet);
System.out.println("hashSet中是否包含count为-3的R对象?" + hashSet.contains(new R(-3)));
System.out.println("hashSet中是否包含count为-2的R对象?" + hashSet.contains(new R(-2)));
}
}
结果如下;
当进行删除-3的元素的时候,他会计算hashcode找到是集合中第二个元素,然后再与count = -3 的R对象进行equals比较,这时候返回为true。所以可以进行删除。当比较count = -3时,由于它去找hashcode的位置没有找到-3,当比较count=-2时,它找的是集合中第一个元素,再与count = -2 的R对象进行equals比较,这时候返回为false,所以,返回false。所以,这将导致HashSet不能正确访问集合中元素。
所以:当程序把可变对象添加到HashSet中之后,不要再去修改该集合中参与计算的hashCode() equals()的实例变量,否则将导致HashSet无法正确操作这些集合元素。
LinkedHashSet
HashSet子类:判断元素相等方法一样,也是根据hashCode值来决定元素存储位置,但同时使用链表来维护元素次序。
package LinkedHashSet;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
public static void main(String[] args) {
LinkedHashSet linkedHashSet = new LinkedHashSet();
linkedHashSet.add("nihao");
linkedHashSet.add("world");
linkedHashSet.add("xiaoming");
System.out.println(linkedHashSet);
linkedHashSet.remove("nihao");
linkedHashSet.add("nihao");
System.out.println(linkedHashSet);
}
}
测试如下:
TreeSet
TreeSet可以确保集合元素处于排序状态
简单例子如下:
package TreeSet;
import java.util.TreeSet;
class M{
int age;
public M() {
}
public M(int age) {
this.age = age;
}
@Override
public String toString() {
return "M{" +
"age=" + age +
'}';
}
}
/**
* 将集合TreeSet中的元素按照age降序排列
*/
public class TreeSetTest {
public static void main(String[] args) {
//TreeSet集合元素需要实现comparable接口
TreeSet<M> ts = new TreeSet<M>(((o1, o2) -> {
M m1 = o1;
M m2 = o2;
if(m1.age > m2.age){
return -1;
}else if (m1.age < m2.age){
return 1;
}else {
return 0;
}
}));
ts.add(new M(5));
ts.add(new M(-3));
ts.add(new M(59));
//如果比较结果返回为0就不会加入了
ts.add(new M(59));
System.out.println(ts);
}
}
测试结果:
EnumSet
为枚举专门设计的集合类;
测试代码如下:
package EnumSet;
import java.util.EnumSet;
enum Season{
SPRING,SUMMER,FALL,WINTER
}
/**
* EnumSet在set中性能是最好的,但是集合元素只能是枚举类的枚举值
*/
public class EnumSetTest {
public static void main(String[] args) {
//创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值
EnumSet es1 = EnumSet.allOf(Season.class);
System.out.println(es1);
//创建一个EnumSet空集合,里面只能加Season类中的枚举值
EnumSet es2 = EnumSet.noneOf(Season.class);
es2.add(Season.SPRING);
es2.add(Season.FALL);
System.out.println(es2);
}
}
结果如下: