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