java Set接口和实现类的应用和特点HashSet、LinkedHashSet、TreeSet

1.集合结构

  • Collection接口
    • List接口:存储有序的,可重复的元素
      • ArrayList(主要的实现类)
      • LinkedList(频繁的插入删除操作等)
      • Vector(古老的实现类,线程安全的,但效率远低于ArrayList)
    • Set接口:存储无序的,不可重复的元素
      • HashSet、 LinkedHashSet、TreeSet
  • Map接口:存储“键-值”对的数据
    • HashMap(主要实现类)、LinkedHashMap、TreeMap、HashTable(子类:Properties)

2.Set接口

  1. Set接口是Collection的子接口,set接口没有提供额外的方法,其常用的方法都是Collection常用的
  2. Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
  3. Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法
  4. demo
public class TestSet {

	@Test
	public void testHashSet() {
		Set set = new HashSet<>();
		set.add(123);
		set.add(456);
		set.add("AA");
		set.add("AA");
		set.add("BB");
		set.add(null);
		
		Person p1 = new Person("GG",23);
		Person p2 = new Person("GG",23);
		System.out.println(p1.equals(p2));
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());
		set.add(p1);
		set.add(p2);
		System.out.println(set.size());		
		System.out.println(set);
	}
}//Peson类在最下方
  1. 无序性:无序性不等于 随机性 (内存空间存的位置是无序的),真正的无序性,指定是元素在底层存储位置是无序的。
  2. 不可重复性:当向Set添加相同的元素的时候,后面不能添加进去。
    说明:要求添加进去Set中的元素所在的类,一定要重写equals()和hashCode()方法进而保证Set中的不可重复性!
  3. Set中的元素是如何存储的呢?
    当向Set中添加对象时,首先调用此对象的所在类的hashCode()方法,计算此对象的hash值,决定了此对象在Set中的存储位置,若此位置之前没有对象,则此对象直接存到这个位置,若此位置已有对象存储,再通过equals()比较两个对象是否相同,如果相同,则后一个对象不能再添加进来。
    万一返回false呢?都能存储在一个位置。(不建议这样使用)

要求:hashCode()方法要与equals()方法一致。即一致重写。

3. Set接口的实现类之一:HashSet (主要实现类)

  1. HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。

  2. HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。

  3. HashSet 具有以下特点:
    ①不能保证元素的排列顺序
    ②HashSet 不是线程安全的
    ③集合元素可以是 null

  4. 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。

  5. HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

  6. demo参照Set接口的。

4.hashCode() 方法

  1. 如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
  2. 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。
  3. 重写 hashCode() 方法的基本原则
    ①在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值
    ②当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等
    ③对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值

5.Set接口实现类之二:LinkedHashSet

  1. LinkedHashSet 是 HashSet 的子类
  2. LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
  3. LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
  4. LinkedHashSet 不允许集合元素重复。
  5. LinkedHashSet:使用了链表维护了一个添加进集合中的顺序,导致当我遍历LinkedHashSet集合元素的时候,是按照添加进去的顺序遍历的
  6. demo
@Test
public void testLinkedHashSet() {
	Set set = new LinkedHashSet<>();
	set.add(123);
	set.add(456);
	set.add("AA");
	set.add("AA");
	set.add("BB");
	set.add(null);
	Iterator iterator = set.iterator();
	while(iterator.hasNext()) {
		System.out.println(iterator.next());//遍历顺序不变
	}
}
  1. 内存图
    内存图

6.Set实现类之三:TreeSet

  1. TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。

  2. TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。

  3. 向TreeSet中添加的元素必须是同一个类型的。

  4. 由于TreeSet较为特殊,另写在其他博客

  5. TreeSet的方法:

Comparator comparator()
Object first()
Object last()
Object lower(Object e)
Object higher(Object e)
SortedSet subSet(fromElement, toElement)
SortedSet headSet(toElement)
SortedSet tailSet(fromElement)

7.父类

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 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;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		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;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值