java集合Set接口HashSet, TreeSet, LinkedHashSet分析比较

本文详细介绍了Java集合中的Set接口,包括无序且不允许重复的HashSet,有序的TreeSet以及保持插入顺序的LinkedHashSet。内容涉及它们的实现原理、添加元素的规则以及如何根据需求选择合适的Set实现类。
摘要由CSDN通过智能技术生成

Set接口:
一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。

1、无序的
2、不允许重复
3、常用的实现类:HashSet, LinkedHashSet, TreeSet
 
 
HashSet类:

public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, Serializable
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

实现原理:
1、基于哈希表(HashMap)实现
2、不允许重复,可以有一个null
3、不保证顺序恒久不变
4、添加元素,作为HashMap的key存储,value使用一个固定的object对象补充
5、排除重复元素是通过equals来检查对象是否相同
6、判断两个对象是否相同,先判断两个对象的hashCode是否相同(如果两个对象的hashCode相同,不一定是同一个对象,如果不同,那一定不是同一个对象),如果不同,则两个对象不是同一个对象,如果相同,还要进行判断equals判断,equals相同则是同一个对象,不同则不是同一个对象。
7、自定义对象要认为属性值都相同时为一个对象,有这种需求时,那么我们要重写对象所在类的hashCode和equals方法

hashCode分析
hashCode()方法在Object类中定义如下:
public native int hashCode();
hashCode是本地方法,它的实现是根据本地机器相关,当然我们可以在自己写的类中覆盖hashCode()方法,比如String、Integer、Double。。。等等这些类都是覆盖hashCode()方法的。

在java的集合中,判断两个对象是否相等的规则是:
1、判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等,结束;如果相等转入2
2、判断两个对象用equals运算是否相等,如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等
(equals()是判断两个对象是否相等的关键)
 
 
TreeSet类

public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable
基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

有序的,基于TreeMap(二叉树数据结构),对象需要比较大小,通过对象比较器来实现,对象比较器还可以用来去除重复元素,如果自定义的数据类没有实现比较器接口,将无法添加到TreeSet集合中。
 
 
LinkedHashSet

public class LinkedHashSet<E>extends HashSet<E>implements Set<E>, Cloneable, Serializable
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)

HashSet, TreeSet, LinkedHashSet如何选择?
如果要排序,选择TreeSet
如果不要排序,也不用保证排序选择HashSet
不用排序,要保证顺序,选择LinkedHashSet

代码示例:
测试类

package com.booy;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;
public class SetDemo {
	public static void main(String[] args) {
		//hashSet();
		//treeSet();
		linkedHashSet();
	}
	private static void linkedHashSet() {

		Dog d1 = new Dog("小虎",3,5);
		Dog d2 = new Dog("肉肉",4,2);
		Dog d3 = new Dog("彪哥",6,4);
		Dog d4 = new Dog("彪哥",6,4);
		
		LinkedHashSet<Dog> set = new LinkedHashSet<>();
		set.add(d1);
		set.add(d2);
		set.add(d3);
		set.add(d4);
		for(Dog d:set) {
			System.out.println(d);
		}
	}
	private static void treeSet() {

		Dog d1 = new Dog("小虎",3,5);
		Dog d2 = new Dog("肉肉",4,2);
		Dog d3 = new Dog("彪哥",6,4);
		Dog d4 = new Dog("彪哥",6,4);
		
		TreeSet<Dog> tree = new TreeSet<>(new DogComparator());
		tree.add(d1);
		tree.add(d2);
		tree.add(d3);
		tree.add(d4);
			System.out.println(tree.size());
	}	
	private static void hashSet() {
		HashSet<String> list = new HashSet<>();
		list.add("王一");
		list.add("王二");
		list.add("王三");
		list.add("王四");
		list.add("王五");
		//遍历set集合
		for(String s:list) {
			System.out.println(s);
		}
		Dog d1 = new Dog("小虎",3,5);
		Dog d2 = new Dog("肉肉",4,2);
		Dog d3 = new Dog("彪哥",6,4);
		Dog d4 = new Dog("彪哥",6,4);
		
		HashSet<Dog> dog = new HashSet<>();
		dog.add(d1);
		dog.add(d2);
		dog.add(d3);
		dog.add(d4);
		for(Dog d:dog ) {
			System.out.println(d);
		}
		System.out.println("d1 = "+d1.hashCode());
		System.out.println("d2 = "+d2.hashCode());
		System.out.println("d3 = "+d3.hashCode());
		System.out.println("d4 = "+d4.hashCode());
		System.out.println(dog.size());
	}	
}

DogComparator类:

package com.booy;

import java.util.Comparator;

public class DogComparator implements Comparator<Dog>{

	@Override
	public int compare(Dog o1, Dog o2) {
		return o1.getAge()-o2.getAge();
	}

}

Dog类:

package com.booy;

public class Dog {
	private String name;
	private int age;
	private int id;
	public Dog() {
		super();
	}
	public Dog(String name, int age, int id) {
		super();
		this.name = name;
		this.age = age;
		this.id = id;
	}	
	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 int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	@Override
	public String toString() {
		return "Dog [name=" + name + ", age=" + age + ", id=" + id + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.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;
		Dog other = (Dog) obj;
		if (age != other.age)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值