java set集合(完整例子)

java set集合


  set集合与Collection基本相同,没有提供任何额外的方法,实际上set就是Collection,只不过是行为略有不同(set不允许有相同元素)
  会介绍set的3种实现类HashSet、TreeSet、EnumSet

1.HashSet

  HashSet 具有以下特点:
  1. 不能保证元素的排列序列,顺序可能与添加的顺序不同
  2. 不是同步的,假设有了两个以上的线程,同时修改了HashSet的元素,则必须通过代码来保证同步
  3. 集合元素可以是空值
  4. HashSet集合判断两个元素相等,是通过对象的equals()和hashCode()两个方法都相等,所以添加到HashSet集合元素对象需要重写equals()和hashCode()两个方法

 public class Student 
{
    private String name;
    private int age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Student() {
		super();
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	public Student(String name, int age) {
		super();
		this.name = name;
		this.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;
		// 对于任何非null的引用值x,x.equals(null)必须返回false
		if (obj == null)
			return false;
		 // 通过 getClass 判断比较对象类型是否相等
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		// 引入java8 Objects 如果两者相等,返回true(含两者皆空的情形),否则比较两者值是否相等
		return Objects.equals(this.age, other.age) && Objects.equals(this.name, other.name);
	}	
}

  LinkedHashSet是HashSet的一个子类,LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但它同时使用联表维护元素的次序,这样使得圆水泥看起来是以插入的顺序保存的。性能略低于HashSet的性能。

	    HashSet students = new HashSet();
		Student student = new Student("a", 12);
		Student student1 = new Student("a", 12);
		Student student2 = new Student("c", 12);
		Student student3 = new Student("d", 12);
		Student student4 = new Student("e", 12);
		Student student5 = new Student("f", 12);
		students.add(student);
		students.add(student1);
		students.add(student2);
		students.add(student3);
		students.add(student4);
		students.add(student5);
		students.remove(student3);
		students.add(student3);
		System.out.println(students);
		//[Student [name=a, age=12], Student [name=c, age=12], Student [name=d, age=12], Student [name=e, age=12], Student [name=f, age=12]]
		Student student = new Student("a", 12);
		Student student1 = new Student("a", 12);
		Student student2 = new Student("c", 12);
		Student student3 = new Student("d", 12);
		Student student4 = new Student("e", 12);
		Student student5 = new Student("f", 12);
		LinkedHashSet linkedStudents = new LinkedHashSet();
		linkedStudents.add(student);
		linkedStudents.add(student1);
		linkedStudents.add(student2);
		linkedStudents.add(student3);
		linkedStudents.add(student4);
		linkedStudents.add(student5);
		linkedStudents.remove(student3);
		linkedStudents.add(student3);
		System.out.println(linkedStudents);
		//[Student [name=a, age=12], Student [name=c, age=12], Student [name=e, age=12], Student [name=f, age=12], Student [name=d, age=12]]

  输出LinkedHashSet 集合的元素时,元素的顺序总是与添加的元素一致。

2.TreeSet

  TreeSet 具有以下特点:
   1.TreeSet不是根据插入的顺序排序的,而是根据元素的实际值大小来排序的
   2.TreeSet支持两种排序,一个是自然排序,一个是定制排序
   3.如果将一个类对象加入TreeSet需要实现Comparable接口,重写compareTo方法

        TreeSet treeSet = new TreeSet();
		treeSet.add(-1);
		treeSet.add(-9);
		treeSet.add(10);
		treeSet.add(4);
		System.out.println(treeSet.first());//-9
		System.out.println(treeSet.last());//10

  根据上面程序运行的结果可以知道,TreeSet不是根据插入的顺序排序的,而是根据元素的实际值大小来排序的

2.1 自然排序

   TreeSet 会调用集合元素的compareTo(Object obj)方法来计较元素之间的大小关系,然后将结合按升序排列,这种方式就是自然排序

2.1.1 java的一些常用类已经实现了Comparable接口

   下面是实现了Comparable接口的常用类:
   1.Integer:所有数值类型的包装类
   2.Character:按照字符的UNICODE值进行比较
   3.Boolean: true对应的包装类实例大于false对应的包装类实例
   4.String:按字符串中字符的UNICODE值进行比较
   5.Date、Time:后面的时间、日期比前面的时间、日期大

2.1.2 自定义类实现Comparable接口

  将一个自定义对象添加到TreeSet时,则该对象的类必须实现Comparable接口,否则程序出现异常。
  java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值。例如obj1.compareTo(obj2),如果改方法返回0,则表明两者相等,如果该方法返回一个正整数,则表明obj1大于obj2;如果该方法返回一个负数则表明obj1小于obj2。对于TreeSET集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过compareTo方法比较式返回0——如果返回0,TreeSet则会人为它们相等,否则就认为它们不相等

	    TreeSet objTreeSet = new TreeSet();
		Product a = new Product(3.14);
		Product b = new Product(5.67);
		Product c = new Product(3.14);
		objTreeSet.add(a);
		objTreeSet.add(b);
		objTreeSet.add(c);
		System.out.println(objTreeSet);
		//[Product [price=3.14], Product [price=5.67]]
2.2 定制排序

   TreeSet 的自然排序是根据集合元素的大小,TreeSet 将它们以升序排列。如果需要实现定制排序,则可以通过Comparator接口帮助。该接口里包含一个int compare(T o1, T o2),该方法用于比较o1和o2,如果该方法返回正整数,则表明o1大于o2;如果该方法返回0,则表明o1等于o2;如果该方法返回负整数,则表明o1小于o2。
  如果需要实现定制排序,则需要在创建TreeSet集合对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合源的排序逻辑。由于Comparator 是一个函数式接口,因此可以使用Lambda表达式来代替Comparator对象。

public class Food 
{
    private double price;

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public Food(double price) {
		super();
		this.price = price;
	}

	@Override
	public String toString() {
		return "Food [price=" + price + "]";
	}

	public Food() 
	{
		super();
		// TODO Auto-generated constructor stub
	}
}
public class FoodComparator implements Comparator<Food> {

	@Override
	public int compare(Food o1, Food o2) 
	{
		//从小到大排序
		if (o1.getPrice() > o2.getPrice())
		{
			return 1;
		}
		else if (o1.getPrice() == o2.getPrice())
		{
			return 0;
		}
		else
		{
			return -1;
		}
	}
}
	    FoodComparator foodComparator = new FoodComparator();
		TreeSet foodTreeSet = new TreeSet(foodComparator);
		Food food1 = new Food(1);
		Food food2 = new Food(2);
		Food food3 = new Food(3);
		foodTreeSet.add(food3);
		foodTreeSet.add(food1);
		foodTreeSet.add(food2);
		TreeSet foodTreeSet2 = new TreeSet(( o1, o2)->{
			Food f1 = (Food)o1;
			Food f2 = (Food)o2;
			return f1.getPrice() > f2.getPrice() ? 1 : f1.getPrice() == f2.getPrice() ? 0 : -1;
		
	     }) ;
		foodTreeSet2.add(food3);
		foodTreeSet2.add(food1);
		foodTreeSet2.add(food2);
		System.out.println(foodTreeSet);
		System.out.println(foodTreeSet2);

  上述代码可以看出,由于Comparator 是一个函数式接口,因此可以使用Lambda表达式来代替Comparator对象。代码由此变得简洁许多。

2.3 附加讲解TreeMap
        TreeMap map = new TreeMap();
		map.put(3, 2);
		map.put(1, 2);
		map.put(5, 2);
		map.put(4, 2);
		System.out.println(map);
		TreeMap productMap = new TreeMap();//{1=2, 3=2, 4=2, 5=2}
		productMap.put(new Product(3), 1);
		productMap.put(new Product(2), 5);
		productMap.put(new Product(5), 2);
		productMap.put(new Product(4), 10);
		System.out.println(productMap);//{Product [price=2.0]=5, Product [price=3.0]=1, Product [price=4.0]=10, Product [price=5.0]=2}
		TreeMap<Product, Integer> productMap2 = new TreeMap<Product, Integer>((o1,o2)-> {Product p1 = (Product)o1; Product p2 = (Product)o2; return p1.getPrice() > p2.getPrice() ? 1 : p1.getPrice() == p2.getPrice() ? 0 : -1;});
		productMap2.put(new Product(3), 1);
		productMap2.put(new Product(2), 5);
		productMap2.put(new Product(5), 2);
		productMap2.put(new Product(4), 10);
		System.out.println(productMap2);//{Product [price=2.0]=5, Product [price=3.0]=1, Product [price=4.0]=10, Product [price=5.0]=2}

  TreeMap key值部分等同于TreeSet

3.EnumSet

  EnumSet 是一个专为枚举类设计的集合类,EnumSet 中的所有元素都必须是指定枚举类型的枚举值。
  EnumSet 类没有暴露任何构造器来创建该类实例,程序通过该类的方法来参加EnumSet 类实例。Enum 类提供了如下常用方法来创建EnumSet对象:
在这里插入图片描述
   实例:

public class EnumSetTest 
{
	enum Color
	{
		BLUE,YELLOW,RED,GREEN;
	}
    public static void main(String[] args) 
    {
		EnumSet enumSet = EnumSet.allOf(Color.class);
		System.out.println(enumSet);//[BLUE, YELLOW, RED, GREEN]
		EnumSet noneEnumSet = EnumSet.noneOf(Color.class);
		System.out.println(noneEnumSet);//[]
		EnumSet enumSet1 = EnumSet.of(Color.BLUE,Color.RED);
		enumSet1.add(Color.GREEN);
		System.out.println(enumSet1);//[BLUE, RED, GREEN]
		EnumSet enumSet2 = EnumSet.range(Color.YELLOW, Color.GREEN);
		System.out.println(enumSet2);//[YELLOW, RED, GREEN]
		EnumSet enumSet3 = EnumSet.complementOf(enumSet2);
		System.out.println(enumSet3);//[BLUE]
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值