set的集合

思维导图

一.set集合特点&遍历方式

set集合的特点:不重复基本数据类型
&字符串常量 String str=“abc”;
&引用对象 String str = new String();

代码块:

package com.jiangwenjuan.set;

import java.util.HashSet;
import java.util.Iterator;

/**
 * set集合的特点
 * 	不重复,基本数据类型&String = "acb";  &String str = new String();
 * 
 * 
 * @author 蒋文娟
 *
 * @date 2022年6月8日 下午4:42:02
 */
public class Demo1 {
	public static void main(String[] args) {
		HashSet set = new HashSet<>();
		set.add("zs");
		set.add("ls");
		set.add("ww");
		set.add("老六");
		set.add("ls");
		System.out.println(set.size());
		
		System.out.println("========增强for==========");
		for (Object obj : set) {
			System.out.println(obj);
		}
		
		System.out.println("========迭代器==========");
		
		Iterator it = set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		
	}

}

结果:

4
========增强for==========
ww
老六
ls
zs
========迭代器==========
ww
老六
ls
zs

二.set集合去重原理

set底层去重原理:
1.set去重底层原理是与对象的hashCode以及equals方法相关
2.判断重复元素的时候,是先比较hashCode值,在调用equals比较内容

①.set去重底层原理是与对象的hashCode以及equals方法相关

代码块:

package com.jiangwenjuan.set;

import java.util.HashSet;

/**
 * @author 蒋文娟
 *
 * @date 2022年6月8日 下午6:05:43
 */
public class Demo2 {
	public static void main(String[] args) {
		HashSet set = new HashSet<>();
		set.add(new Person("zs", 18));
		set.add(new Person("ls", 14));// distrinct 在我们手里的时候可以去重,在别人就不能
		set.add(new Person("ww", 24));// 用set去重
		set.add(new Person("老六", 22));
		set.add(new Person("zs", 18));
		System.out.println(set.size());
	}
}
class Person{
	private String name;
	private int 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;
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public int hashCode() {
		System.out.println("===========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) {
		System.out.println("===========equals===========");
		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;
	}
	
}

结果:

===========hashCode===========
===========hashCode===========
===========hashCode===========
===========hashCode===========
===========hashCode===========
===========equals===========
4

如果hashCode哪里返回的是1的话,结果为一样也为四:

===========hashCode===========
===========hashCode===========
===========equals===========
===========hashCode===========
===========equals===========
===========equals===========
===========hashCode===========
===========equals===========
===========equals===========
===========equals===========
===========hashCode===========
===========equals===========
4

②、判断重复元素的时候,是先比较hashCode值,在调用equals比较内容

package com.jiangwenjuan.set;

import java.util.HashSet;

/**
 * 	set底层去重原理
 * 	1.set去重底层原理是与对象的hashCode以及equals方法相关
 * 	2.判断重复元素的时候,是先比较hashCode值,在调用equals比较内容
 * 
 * @author 蒋文娟
 *
 * @date 2022年6月8日 下午6:05:43
 */
public class Demo2 {
	public static void main(String[] args) {
		HashSet set = new HashSet<>();
		set.add(new Person("zs", 18));
		set.add(new Person("ls", 14));// distrinct 在我们手里的时候可以去重,在别人就不能
		set.add(new Person("ww", 24));// 用set去重
		set.add(new Person("老六", 22));
		set.add(new Person("zs", 18));
		System.out.println(set.size());
	}
}
class Person{
	private String name;
	private int 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;
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public int hashCode() {
		System.out.println("===========hashCode===========");
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return 1;
	}
	@Override
	public boolean equals(Object obj) {
		System.out.println("===========equals===========");
//		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;
	}
	
}

③、这两个的区别就在于,一个是为4,一个为1

		set.add(new Person("zs", 18));
		set.add(new Person("ls", 14));
		set.add(new Person("ww", 24));
		set.add(new Person("老六", 22));
		set.add(new Person("zs", 18));

原理1:第一个加进去时候不需要比较,当第二加进去的时候,就跟第一个比较一次,再第三个加进去的时候比较两次,以此类推,当第五个加进去的时候就比较四次了。
equals的判断要留下。

原理2:当hasCode为1的时候,equals也为true的时候,就判定为了一个元素。

底层的基础原理就两个:先调用hashCode的值,相等,在去比equals,如果hashCode都不相等,就不会去调用equals方法了。

@Override
	public int hashCode() {
		System.out.println("===========hashCode===========");
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return 1;
	}
	@Override
	public boolean equals(Object obj) {
		System.out.println("===========equals===========");
//		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;
	}

三.set集合自然排序接口

①.需求:从xxx公司,拿到用户数据,需要根据用户的级别,进行会议座位的排序

张三 部门总监 1
李四 普通员工 3
王五 部门经理 2。。

现象:1.String默认是能够排序的
2.自定义的对象无法排序,报类型转换异常

实体类:

class Person implements Comparable<Person>{
	
	private String name;
	private int age;
	private int level;
	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 Person(String name, int age, int level) {
		super();
		this.name = name;
		this.age = age;
		this.level = level;
	}
	public int getLevel() {
		return level;
	}
	public void setLevel(int level) {
		this.level = level;
	}
	public Person() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public int hashCode() {
		System.out.println("===========hashCode===========");
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return 1;
	}
	@Override
	public boolean equals(Object obj) {
		System.out.println("===========equals===========");
		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;
	}
	@Override
	public int compareTo(Person o) {
		// TODO Auto-generated method stub
		return this.level - o.level;
	}
	

代码块:

package com.jiangwenjuan.set;

import java.util.TreeSet;

/**
 *  set集合排序
 * @author 蒋文娟
 *
 * @date 2022年6月8日 下午6:52:23
 */
public class Demo3 {
	public static void main(String[] args) {
		
		/**
		 * 	张三	部门总监	1
		 * 	李四	普通员工	3
		 * 	王五	部门经理	2
		 * 	。。 
		 * xxxService.list(1);
		 * 
		 * 	现象:
		 * 	1.String默认是能够排序的
		 * 	2.自定义的对象无法排序,报类型转换异常
		 */
		
//		Exception in thread "main" java.lang.ClassCastException: 类型转换异常
//		com.jiangwenjuan.set.Person cannot be cast to java.lang.Comparable
//							这个Person的类不能强制转换为Comparable接口
		TreeSet set = new TreeSet<>();
		set.add(new Person("张三", 18, 1));
		set.add(new Person("李四", 24, 4));
		set.add(new Person("王五", 26, 2));
		set.add(new Person("老六", 20, 3));
		for (Object Object : set) {
			System.out.println(Object);
		}
	}
}

这里就已经按会议座位排序了,结果:

Person [name=张三, age=18, level=1]
Person [name=王五, age=26, level=2]
Person [name=老六, age=20, level=3]
Person [name=李四, age=24, level=4]

②.需求:按照年龄升序,打印出人员信息

主要是要修改实体类中重写的compareTo方法
实体类: 这里也按照了年龄和等级的比较

@Override
	public int compareTo(Person o) {
		int levelRes = this.level - o.level;
		return levelRes == 0 ? this.age - o.age:levelRes;
	}

代码块:多加了一个八戒

TreeSet set = new TreeSet<>();
		set.add(new Person("张三", 18, 1));
		set.add(new Person("李四", 24, 4));
		set.add(new Person("王五", 26, 2));
		set.add(new Person("老六", 20, 3));
		set.add(new Person("八戒", 18, 3));
		for (Object Object : set) {
			System.out.println(Object);
		}

结果为

Person [name=张三, age=18, level=1]
Person [name=王五, age=26, level=2]
Person [name=八戒, age=18, level=3]
Person [name=老六, age=20, level=3]
Person [name=李四, age=24, level=4]

③.需求:按照用户的首字母排序以及上面两个需求,都要满足

set集合排序
1. java.lang.Comparable:自然排序 排序的规则是单一的,不能够应对复杂的变化的需求
2. java.util.comparator:比较器排序
专门用来做比较的

TreeSet set = new TreeSet<>(comparator)

实体类的实现implements Comparable<Person>把它注释掉,最后的compareTo也注释掉。

这里有的小问题那是因为代码问题:
代码块:

package com.jiangwenjuan.set;

import java.util.Comparator;
import java.util.TreeSet;

/**
 * @author 蒋文娟
 *
 * @date 2022年6月8日 下午6:52:23
 */
public class Demo3 {
	public static void main(String[] args) {
		
		/**
		 * 	需求1:从xxx公司,拿到用户数据,需要根据用户的级别,进行会议座位的排序
		 * 
		 * 	需求2:
		 * 	按照年龄升序,打印出人员信息
		 * 	
		 * 	需求3:
		 * 	按照用户的首字母排序
		 */
		
//		Exception in thread "main" java.lang.ClassCastException: 类型转换异常
//		com.jiangwenjuan.set.Person cannot be cast to java.lang.Comparable
//							这个Person的类不能强制转换为Comparable接口
		TreeSet set = new TreeSet<>(new levelCompartor());
		set.add(new Person("张三", 18, 1));
		set.add(new Person("李四", 24, 4));
		set.add(new Person("王五", 26, 2));
		set.add(new Person("老六", 20, 3));
		set.add(new Person("八戒", 18, 3));
		for (Object Object : set) {
			System.out.println(Object);
		}
	}
	
	

	
}



class levelCompartor implements Comparator<Person>{

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

然而这里的结果是只有四个,那是因为代码问题:

Person [name=张三, age=18, level=1]
Person [name=王五, age=26, level=2]
Person [name=老六, age=20, level=3]
Person [name=李四, age=24, level=4]

怎么解决呢?就是按照我们之前的哪个写法一样的

class levelCompartor implements Comparator<Person>{

	@Override
	public int compare(Person o1, Person o2) {
		int levelRes = o1.getLevel() - o2.getLevel();
		return levelRes == 0?o1.getAge() - o2.getAge():levelRes;
	}
	
}

结果就出来了:

Person [name=张三, age=18, level=1]
Person [name=王五, age=26, level=2]
Person [name=八戒, age=18, level=3]
Person [name=老六, age=20, level=3]
Person [name=李四, age=24, level=4]

注意:这一种方式相较于其他的方式有什么优点,它能够针于对同样的一组数据,做不同的处理,什么意思呢,就是那么我的需求发生了变化,我要按照这个字母的方式去对比,那么我可以根据不同的需求只要改正一个地方就可以了,假如说:我的A模块要按照名字或者等级排序那么就只要写上面的代码就可以了,那么在另外一个地方就要看下面的代码块了。

四.set集合比较器排序

这些数据假如不来于你的数据库,来自别人的

set.add(new Person("zs", 18, 1));
set.add(new Person("ls", 24, 4));
set.add(new Person("ww", 26, 2));
set.add(new Person("laoliu", 20, 3));
set.add(new Person("bajie", 18, 3));

有一个菜单,用户管理、会议管理、档案管理。如果想实现这些需求
在这里插入图片描述

代码块,就只需要这样就可以了

TreeSet<Person> set = new TreeSet<>((x,y)-> x.getName().compareTo(y.getName()));

按照名字的排序结果:

Person [name=bajie, age=18, level=3]
Person [name=laoliu, age=20, level=3]
Person [name=ls, age=24, level=4]
Person [name=ww, age=26, level=2]
Person [name=zs, age=18, level=1]

代码块:

TreeSet<Person> set = new TreeSet<>((x,y)-> x.getAge() - y.getAge());

按照年龄排序结果:这里有少了一个怎么解决呢?

Person [name=zs, age=18, level=1]
Person [name=laoliu, age=20, level=3]
Person [name=ls, age=24, level=4]
Person [name=ww, age=26, level=2]

解决方法:

TreeSet<Person> set = new TreeSet<>((x,y)-> {
			int ageRes = x.getAge() - y.getAge();
			int leveRes = 0;
			if(ageRes == 0) {
				leveRes = x.getLevel() - y.getLevel();
			}
			else {
				return ageRes;
			}
			return leveRes;
		});

正确的结果:

Person [name=zs, age=18, level=1]
Person [name=bajie, age=18, level=3]
Person [name=laoliu, age=20, level=3]
Person [name=ls, age=24, level=4]
Person [name=ww, age=26, level=2]

只要改代码就可以了,不会写s的,不管你的需求怎么变,我们的可以进行有效的处理。这就是比较序排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值