聊聊java集合Set

130 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

Set是Java中的集合类,提供了一种无顺序,不重复的集合。常用的子类包括HashSet, TreeSet等。

HashSet底层使用HashMap实现,根据元素的hashCode和equals来判断是否为重复元素。当元素的hashCode相同且equals返回true时则认为是重复元素。因为使用了hash算法所以HashSet有很好的添加和访问性能。可以放入null但只能放一个null

TreeSet底层使用红黑树实现,Set上的元素被放在一个自动排序的红黑树中。不能放入null

HashSet

它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。

package com.chen;
 
import java.util.HashSet;
import java.util.Set;
 
	private static void hashSet() {
		Set<String> set = new HashSet();
		set.add("周泰");
		set.add("关羽");
		set.add("戏志才");
		set.add("张角");
		set.add("袁术");
		set.add("曹操");
		String[] names = set.toArray(new String[]{});
		for(String s:names) {
			System.out.println(s);
		}
		Cat c1 = new Cat("喵喵",5,"公");
		Cat c2 = new Cat("咪咪",3,"母");
		Cat c3 = new Cat("奶茶",4,"母");
		Cat c4 = new Cat("喵喵",5,"公");
		Set<Cat> cats = new HashSet<>();
		cats.add(c1);
		cats.add(c2);
		cats.add(c3);
		cats.add(c4);
		cats.add(c2);
		System.out.println(cats.size());
		
		for(Cat c:cats) {
			System.out.println(c);
		}
		
		System.out.println("c1="+c1.hashCode());
		System.out.println("c2="+c2.hashCode());
		System.out.println("c3="+c3.hashCode());
		System.out.println("c4="+c4.hashCode());
	} 
	
	public static void main(String[] args) {
 
	}
 
}
package com.chen;
 
public class Cat {
 
	private String name;
	private int age;
	private String sex;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "Cat [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
	public Cat(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public Cat() {
		super();
	}
	@Override
	public int hashCode() {
		final int prime = 31;//系数 
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((sex == null) ? 0 : sex.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Cat other = (Cat) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (sex == null) {
			if (other.sex != null)
				return false;
		} else if (!sex.equals(other.sex))
			return false;
		return true;
	}
	
}

LinkedHashSet

HashSet的子类,它具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。

private static void linkHashSet() {
		LinkedHashSet<Cat> set = new LinkedHashSet<>();
		Cat c1 = new Cat("喵喵",5,"公");
		Cat c2 = new Cat("咪咪",3,"母");
		Cat c3 = new Cat("奶茶",4,"母");
		Cat c4 = new Cat("喵喵",5,"母");
		set.add(c1);
		set.add(c2);
		set.add(c3);
		set.add(c4);
		
		for(Cat c:set) {
			System.out.println(c);
		}
	}

TreeSet

使用元素的自然顺序对元素进行排序,引用数据类型使用比较器(Comparator)

排序:数字 ==> 英文(忽略大小写) ==> 中文

不可以添加的null元素,不然会java.lang.NullPointerException

private static void treeSet() {
		TreeSet<Cat> tree = new TreeSet<>(new CatComparator());
		Cat c1 = new Cat("喵喵",5,"公");
		Cat c2 = new Cat("咪咪",3,"母");
		Cat c3 = new Cat("奶茶",4,"母");
		Cat c4 = new Cat("喵喵",5,"母");
		tree.add(c1);
		tree.add(c2);
		tree.add(c3);
		tree.add(c4);
		System.out.println(tree.size());
		
		for(Cat c:tree) {
			System.out.println(c);
		} 
	}