天天看点

Java集合-Set接口-HashSet和TreeSet实现类

Java集合 -> Set接口 -> HashSet和TreeSet

1. Set接口特性

  • Set接口继承自Collection,Set 接口中没有新增方法,方法和Collection保持一致;
  • Set特点:无序、不可重复。无序指的是Set中的元素没有索引,因此只能通过遍历查找。
  • Set的常用实现类:HashSet、TreeSet等。
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
//Set接口的基本使用
public class SetTest {
    public static void main(String[] args) {
        Collection<String> c = new HashSet<>();
        c.add("aa");
        c.add("bb");
        c.add("cc");
        c.add("cc");
        //c.remove("aa");
        for(String s : c){
            System.out.println(s);
        }
        System.out.println(c.contains("aa")); //false
        System.out.println(c.size()); //2
        //c.clear();
        //System.out.println(c.isEmpty()); //true

        //通过迭代器遍历
        Iterator it = c.iterator();
        while(it.hasNext()){
            System.out.print(it.next() + " ");  //aa bb cc
        }
        System.out.println();

        Collection<String> c1 = new HashSet<>();
        c1.add("cc");
        c1.add("dd");
        c1.add("ee");
        c1.add("ff");

        c1.removeAll(c);
        for(String s : c1){
            System.out.println(s);
        }
        //c1.retainAll(c);
        it = c1.iterator();
        while(it.hasNext()){
            System.out.print(it.next() + " ");
        }
        System.out.println();
        Object[] ob = c1.toArray();
        System.out.println(Arrays.toString(ob)); //[dd, ee, ff]
    }
}
           

2. HashSet底层模拟实现

  • HashSet的add方法时通过HashMap的put方法实现的,不过HashMap是key-value键值对,而HashSet是集合,HashSet添加的元素是存放在HashMap的key位置上,而value取了默认常量PRESENT,是一个空对象。
  • HashSet的remove方法通过HashMap的remove方法来实现
import java.util.HashMap;

public class MyHashSet<E> {
    private transient HashMap<E,Object> map;
    private static final Object PRESENT = new Object();

    public MyHashSet(){
        map = new HashMap<>();
    }

    /**
     * 添加元素
     * @param e
     * @return
     */
    public void add(E e) {
        map.put(e, PRESENT);
    }

    public int size(){
        return map.size();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(E e:map.keySet()){
            sb.append(e + ",");
        }
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }

    public static void main(String[] args) {
        MyHashSet<String> mhs = new MyHashSet<>();
        mhs.add("a");
        mhs.add("b");
        mhs.add("c");
        mhs.add("c");
        mhs.add("eee");

        System.out.println(mhs.size()); //4
        System.out.println(mhs); //[a,b,c,eee]
    }
}
           

3. TreeSet

  • TreeSet底层实际是用TreeMap实现的,内部维护一个简化版的TreeMap通过key来存储Set的元素。
  • TreeSet内部需要对存储的元素进行排序,因此,对应的类需要实现Comparable接口,这样才能根据compareTo()方法比较对象之间的大小,才能进行内部排序。
import java.util.TreeSet;
public class MyTreeSet {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<>();
        ts.add(10000);
        ts.add(300);
        ts.add(1500);
        ts.add(5000);
        for(Integer integer : ts){
            System.out.println(integer);
        }

        TreeSet<Student> ts1 = new TreeSet<>();
        ts1.add(new Student(1006,"Ano",88));
        ts1.add(new Student(1005,"Jackson",66));
        ts1.add(new Student(1001,"Charlie",90));
        ts1.add(new Student(1003,"Charlie",90));
        for(Student stu : ts1){
            System.out.println(stu);
        }
    }
}

class Student implements Comparable<Student>{
    int id;
    String name;
    int score;

    public Student(int id, String name, int score){
        super();
        this.id = id;
        this.name = name;
        this.score = score;

    }

    @Override
    public String toString() {
        return this.id + "->" + this.name + "->" + this.score;
    }

    @Override
    public int compareTo(Student o) {
        if(this.score > o.score){
            return 1;
        }else if(this.score < o.score){
            return -1;
        }else{
            if(this.id > o.id){
                return 1;
            }else if(this.id < o.id){
                return -1;
            }else{
                return 0;
            }
        }

    }
}