java -- set各集合学习小结

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);
    }

}

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值