Java数据结构之集合Set

概念

Set是一个不包含重复元素的集合,。所谓重复元素即e1.equals(e2) == true;时,我们说这两个元素重复。这个集合中最多只能有一个空(null)元素。Set集合是否有序,需要看具体的实现类。

常用实现类分析

一、HashSet

HashSet是无序的集合。去重方式是先通过将要插入的元素的hashCode在内存中查找指定区域,没有元素的话,就直接插入,有的话就用equals比较已存在元素和将要插入的元素,返回true,则视为重复,不会插入新元素。
下面的代码演示执行hashCode和equals方法的顺序,例子不太恰当,但足以说明问题,可以修改创建Person对象时的初始化值进行各种测试:

import java.util.HashSet;
import java.util.Set;

public class TestSet {

	public static void main(String[] args) {
		testHashSet();
	}
	
	public static void testHashSet() {
		Set<Person> persons = new HashSet<Person>();
		persons.add(new Person("墨倾池", "001", 100));
		persons.add(new Person("圣司", "001", 200));
		for (Person p : persons) {
			System.out.println(p.name);
		}
	}
	
	private static class Person {

		String name;
		String id;
		int age;
		
		Person(String name, String id, int age) {
			this.name = name;
			this.id = id;
			this.age = age;
		}
		
		@Override
		public int hashCode() {
			System.out.println("获取 " + name + " 的hashCode ");
			return age;
		}

		@Override
		public boolean equals(Object obj) {
			Person p2 = (Person) obj;
			System.out.println("用equals比较 " + name + " 和 " + p2.name);
			return id.equals(p2.id);
		}
		
	}
	
}

二、TreeSet

TreeSet是有序的集合。排序方式有两种:
1.元素对象自身可以进行比较(实现了Comparable接口)
2.创建集合时自身传入了比较器
如果以上两种情况同时符合,将使用第二种;如果都不符合,将报异常 java.lang.ClassCastException: XXX cannot be cast to java.lang.Comparable。
注:TreeSet去重也是通过上面的比较方式去重,即比较时return 0;的话,则表示这两个元素重复。

import java.util.Set;
import java.util.TreeSet;

public class TestTreeSet {

	public static void main(String[] args) {
		// testTreeSet1();
		testTreeSet2();
	}

	public static void testTreeSet1() {
		Set<Person> persons = new TreeSet<Person>();
		persons.add(new Person("4墨倾池", "004", 200));
		persons.add(new Person("2墨倾池", "002", 200));
		persons.add(new Person("3墨倾池", "003", 300));
		persons.add(new Person("1墨倾池", "001", 100));
		for (Person p : persons) {
			System.out.println(p.name);
		}
	}
	
	public static void testTreeSet2() {
		Set<Person> persons = new TreeSet<Person>((o1, o2) -> o2.name.compareTo(o1.name));
		persons.add(new Person("4墨倾池", "004", 200));
		persons.add(new Person("2墨倾池", "002", 200));
		persons.add(new Person("3墨倾池", "003", 300));
		persons.add(new Person("1墨倾池", "001", 100));
		for (Person p : persons) {
			System.out.println(p.name);
		}
	}
	
	private static class Person implements Comparable<Person> {

		String name;
		String id;
		int age;
		
		Person(String name, String id, int age) {
			this.name = name;
			this.id = id;
			this.age = age;
		}
		
		@Override
		public int hashCode() {
			System.out.println("获取 " + name + " 的hashCode ");
			return age;
		}

		@Override
		public boolean equals(Object obj) {
			Person p2 = (Person) obj;
			System.out.println("用equals比较 " + name + " 和 " + p2.name);
			return id.equals(p2.id);
		}

		@Override
		public int compareTo(Person o) {
			System.out.println("用compareTo比较 " + name + " 和 " + o.name);
			return name.compareTo(o.name);
		}
		
	}
	
}

三、LinkedHashSet

LinkedHashSet与HashSet基本类似,不一样的地方就是LinkedHashSet会保存插入的顺序,先进先出类似队列。

import java.util.LinkedHashSet;
import java.util.Set;

public class TestLinkedHashSet {

	public static void main(String[] args) {
		testLinkedHashSet();
	}

	public static void testLinkedHashSet() {
		Set<Person> persons = new LinkedHashSet<Person>();
		persons.add(new Person("4墨倾池", "004", 400));
		persons.add(new Person("2墨倾池", "002", 200));
		persons.add(new Person("3墨倾池", "003", 300));
		persons.add(new Person("1墨倾池", "001", 100));
		for (Person p : persons) {
			System.out.println(p.name);
		}
	}
	
	private static class Person {

		String name;
		String id;
		int age;
		
		Person(String name, String id, int age) {
			this.name = name;
			this.id = id;
			this.age = age;
		}
		
		@Override
		public int hashCode() {
			System.out.println("获取 " + name + " 的hashCode ");
			return age;
		}

		@Override
		public boolean equals(Object obj) {
			Person p2 = (Person) obj;
			System.out.println("用equals比较 " + name + " 和 " + p2.name);
			return id.equals(p2.id);
		}
		
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值