Set 接口常用子类及其特点

  1. Set 集合中元素不可重复,是无序的(存入和取出的顺序是不一样的),
    Set 接口中的方法和 Collection 接口一致.
  2. 常用子类:
    • HashSet : 内部数据结构是哈希表, 是不同步的
      • LinkedHashSet : 存入和取出的顺序一致(有序)
    • TreeSet : 可以对 Set 集合中的元素进行排序, 是不同步的.

HashSet

  1. 哈希表如何确定元素是否相同?
    1. 判断两个元素的哈希值是否相同,其实判断的是对象的 hashCode() 方法
    2. 如果哈希值相同,再判断两个对象的内容是否相同,用的是 equals() 方法
    3. 如果哈希值不同,是不需要判断 equals() 方法的
  2. HashSet 存储自定义对象
// 往 HashSet 集合中存储 Person 对象, 如果年龄和姓名相同,视为同一个人.
// 视为相同元素

// 自定义 Person 对象
public class Person{
    private String name;
    private int age;

    public Person(){
        super();
    }

    public Person(String name, int age){
        super();
        this.name = name;
        this.age = age;
    }

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }

    // 覆盖 Object 类的 hashCode() 方法
    public int hashCode(){

        // 使用 String 类的 hashCode() 方法
        return name.hashCode() + age;
    }

    // 覆盖 Object 类的 equals() 方法
    public boolean equals(Object obj){

        if(this == obj)
            return true;
        if(!(obj instanceof Person))
            throw new ClassCastException("类型错误");

        Person p = (Person)obj;

        // 通过判断两者的姓名和年龄是否相同,确定返回值
        return this.name.equals(p.name) && this.age == p.age;
    }
}

public class HashSetTest{
    public static void main(String[] args){

        HashSet hs = new HashSet();

        /*
         * HashSet 集合数据结构是哈希表,所以存储元素的时候,
         * 首先使用元素的 hashCode() 方法来确定位置; 如果
         * 位置相同, 在通过元素的 equals() 方法来确定元素是否
         * 相同
         */
        hs.add(new Person("lisi1",21));
        hs.add(new Person("lisi2",22));
        hs.add(new Person("lisi3",23));
        hs.add(new Person("lisi4",24));
        hs.add(new Person("lisi4",24));


        Iterator it = hs.iterator();
        while(it.hasNext()){
            Person p = (Person)it.next();
            System.out.println(p.getName()+"..."+p.getAge());
        }
    }
}
  1. 练习: 去除 ArrayList 集合中重复的元素
// ArrayList 集合存储的为字符串

public static void main(String[] args){

    ArrayList al = new ArrayList();

    al.add("abc1");
    al.add("abc");
    al.add("abc2");
    al.add("abc1");
    al.add("abc2");

    System.out.println(al);

    al = getSingleElement(al); // 定义一个方法, 去除重复的元素
    System.out.println(al);
}

public static ArrayList getSingleElement(ArrayList al){

    // 定义一个临时容器
    ArrayList temp = new ArrayList();

    // 迭代 al 集合
    Iterator it = al.iterator();
    while(it.hasNext()){
        Object obj = it.next();

        // 判断被迭代到的元素是否在临时容器中,
        // 如果不在, 则存入临时容器
        if(!temp.contains(obj)){
            temp.add(obj);
        }
    }

    return temp;
}


// ArrayList 集合存储自定义对象

public static void main(String[] args){

    ArrayList al = new ArrayList();

    al.add(new Person("lisi1",21));
    al.add(new Person("lisi2",22));
    al.add(new Person("lisi1",21));
    al.add(new Person("lisi2",22));
    al.add(new Person("lisi3",23));
    al.add(new Person("lisi3",24));

    System.out.println(al);

    al = getSingleElement(al); // 定义一个方法, 去除重复的元素
    System.out.println(al);
}

public static ArrayList getSingleElement(ArrayList al){

    // 定义一个临时容器
    ArrayList temp = new ArrayList();

    // 迭代 al 集合
    Iterator it = al.iterator();
    while(it.hasNext()){
        Object obj = it.next();

        // 判断被迭代到的元素是否在临时容器中,
        // 如果不在, 则存入临时容器
        // Collection 接口中 contains() 方法,判断相同的依据是 equals() 方法

        if(!temp.contains(obj)){
            temp.add(obj);
        }
    }

    return temp;
}

LinkedHashSet

  • 特点: 元素不重复, 且有序(存入和取出的顺序一致)

TreeSet

  • 特点: 可以对 Set 集合中的元素进行指定顺序的排序,是不同步的.元素不可重复.
  • 保证元素唯一性的方式: 根据比较方法(compareTo()) 的返回结果. 如果是 0,就是相同元素.
// TreeSet 集合中存储 Perosn 对象
// TreeSet 集合对元素进行排序的方式一:
// 让元素自身具备比较功能, 元素需要实现 Comparable 接口,
// 覆盖 compareTo() 方法

// 自定义 Person 对象, 实现 Comparable 接口
public class Person implements Comparable {
    private String name;
    private int age;

    public Person(){
        super();
    }

    public Person(String name, int age){
        super();
        this.name = name;
        this.age = age;
    }

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }

    // 覆盖 compareTo() 方法
    // 以 Person 对象的年龄作为依据从小到大进行排序
    // String 类具备 compareTo() 方法, 比较两个字符串的大小
    public int compareTo(Object obj){

        int temp = this.age - p.age;
        return temp == 0 ? this.name.compareTo(p.name) : temp;
    }

}

public class TreeSetTestDemo{
    public static void main(String[] args){

        TreeSet ts = new TreeSet();

        ts.add(new Person("zhangsan",21));
        ts.add(new Person("lisi",22));
        ts.add(new Person("wangwu",24));
        ts.add(new Person("zhaoliu",28));

        while(ts.hasNext()){
            Person p = (Perosn)it.next();

            System.out.println(p.getName()+"..."+p.getAge());
        }
}
}

// TreeSet 集合第二种排序方式:(较常用)
// 应用场景: 不需要按照对象中具备的自然排序进行排序或者对象中不具备自然排序
// 让 TreeSet 集合具备比较功能.
// 定义一个类实现 Comparator 接口, 覆盖 compare 方法.
// 将该类对象作为参数传递给 TreeSet 集合的构造函数.

// 创建一个根据 Person 类的 name 进行排序的比较器
public class ComparatorByName implements Comparator {

    public int compare(Object o1, Object o2){

        Person p1 = (Person)o1;
        Person p2 = (Person)o2;

        int temp = p1.getName().compareTo(p2.getName());

        return temp == 0 ? p1.getAge()-p2.getAge() : temp;
}
}

public class TreeSetTestDemo{
    public static void main(String[] args){

        // 将比较器作为参数传递给 TreeSet 集合的构造函数
        TreeSet ts = new TreeSet(new ComparatorByName());

        ts.add(new Person("zhangsan",21));
        ts.add(new Person("lisi",22));
        ts.add(new Person("wangwu",24));
        ts.add(new Person("zhaoliu",28));

        while(ts.hasNext()){
            Person p = (Perosn)it.next();

            System.out.println(p.getName()+"..."+p.getAge());
        }
}
}
TreeSet 内部结构图解





参考资料

  • JavaSE 基础视频(毕向东)
  • JDK 1.6 中文文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值