集合框架(二)Set集合

目录:

1.set集合的特点

2.Set集合遍历方式

3.HashSet哈希表存储,底层去重原理

4.TreeSet(自然排序,比较器排序)


一,Set集合的特点

        1.无重复,无序(基本数据类型&String才会自动去重)

二,Set集合遍历方式

因为Set集合中没有下标,只能用foreach 以及 迭代器 两种方式输出

1.增强for循环 foreach

2.迭代器

package com.ljj.set;

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

/**
 * set集合的特点
 * 不重复:基本数据类型&String
 * @author Administrator 刘俊杰
 *下午4:37:45
 */
public class Demo1 {
	public static void main(String[] args) {
		HashSet<Object> 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("---------------foreach循环-----------");
		for (Object obj : set) {
			System.out.println(obj);
		}
		
		System.out.println("---------------迭代器--------------");
		Iterator<Object> it=set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}
}

运行结果:

三,HashSet哈希表存储,底层去重原理

案例1,将一个set集合去重,去除name值相同的对象

实体类 以及 已存入对象的set集合

package com.ljj.set;

import java.util.HashSet;
/**
 * set底层去重原理
 * 1.set去重底层原理是对象的hashCode方法以及equals方法相关
 * 2.判断重复元素的时候,是比较hashCode值,在调用equals比较内容
 * @author Administrator 刘俊杰
 *下午4:47:55
 */
public class Demo2 {
	public static void main(String[] args) {
		HashSet<Object> set = new HashSet<>();
		set.add(new Person("ws",18,1));
		set.add(new Person("zh",18,2));//distrinct
		set.add(new Person("ls",85,3));
		set.add(new Person("老六",8,4));
		set.add(new Person("zh",18,1));
		System.out.println(set.size());
	}
}
class Person{
	private String name;//姓名
	private int age;//年龄
	private int dj;//等级
	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 getDj() {
		return dj;
	}
	public void setDj(int dj) {
		this.dj = dj;
	}
	
	public Person() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
	}
	
	public Person(String name, int age, int dj) {
		super();
		this.name = name;
		this.age = age;
		this.dj = dj;
	}
	
}

打印出set集合的长度:5

 因为Set中存的值为对象,不是基本数据类型以及String 所以无法自动去重

方法:重写HashCode以及equals方法

private String name;//姓名
	private int age;//年龄
	private int dj;//等级
	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 getDj() {
		return dj;
	}
	public void setDj(int dj) {
		this.dj = dj;
	}
	
	public Person() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
	}
	
	public Person(String name, int age, int dj) {
		super();
		this.name = name;
		this.age = age;
		this.dj = dj;
	}
	//重写
	@Override
	public int hashCode() {
		System.out.println("=============hashCode============");
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + dj;
		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 (dj != other.dj)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

再次打印结果为:

 结论:

1.不是默认数据类型以及String类型时 去重需要重写hashCode以及equals方法

2.Set去重底层原理与对象的hashCode以及equals方法相关

3.判断重复元素时,先比较hashCode值,再调用equlas比较内容

四,TreeSet(自然排序,比较器排序)

案例2:根据用户的级别进行会议座位的排序

实体类erson:

class Person{
	private String name;//姓名
	private int age;//年龄
	private int dj;//等级
	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 getDj() {
		return dj;
	}
	public void setDj(int dj) {
		this.dj = dj;
	}
	
	public Person() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
	}
	
	public Person(String name, int age, int dj) {
		super();
		this.name = name;
		this.age = age;
		this.dj = dj;
	}
	
}

 TreeSet集合:

package com.ljj.set;

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

/**
 * set集合排序
 * java.lang.Comparable,自然排序 排序的规则是单一的,不能够应对复杂的变化的需求
 * java.util.comparator, 比较级排序
 * @author Administrator 刘俊杰
 *下午5:49:31
 */
public class Demo3 {
	public static void main(String[] args) {
		
		TreeSet set = new TreeSet<>();
		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",28,3));
		set.add(new Person("zs",18,3));
		for (Object obj : set) {
			System.out.println(obj);
			
		}
		
	}

运行结果:Comparable 类型转化异常

 原因:

之前的String类型之所以可以转换无误是因为实现了Comparable接口,而我们自定义的person对象却没有

 解决方法:

把自定义的person类实现Comparable接口,并实现compareTo方法

class Person implements Comparable<Person>{
	private String name;//姓名
	private int age;//年龄
	private int dj;//等级
	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 getDj() {
		return dj;
	}
	public void setDj(int dj) {
		this.dj = dj;
	}
	
	public Person() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", dj=" + dj + "]";
	}
	
	public Person(String name, int age, int dj) {
		super();
		this.name = name;
		this.age = age;
		this.dj = dj;
	}

	/**
	 * 实现方法
	 */
	@Override
	public int compareTo(Person o) {
		return this.dj -o.getDj();
	}
}

 再次运行结果:(成功排序!)

 案例3:在案例一的基础上 按照年龄升序再次进行排序

TreeSet集合以及运行结果:

 从集合中可以看到其中包含了两个年龄相同的对象,一共五条数据,但是结果只有四条,说明此时发生了数据丢失的现象

原因:

运行进行了判断,当属性值相同时,进行了自动去重

所以我们要手动对第二个值进行判断

解决方法:compareTo方法为:

 此时运行结果:(成功)

 案例4:按照姓名首拼音首字母进行升序排序

从前两个案例中发现我们要排序 修改的一直是compareTo方法,使用Comparable接口,也就是自然排序,这种方法太单一,并且太受限制,无法满足更多的复杂的编码需求

这时候就需要使用到我们的第二种方法:实现Comparator接口(比较器排序)

首先在实例化TreeSet时选择实现Comparator接口

 其次,在定义实例化的地方加上比较器来比较首字母

***比较器器代码写错则无效

 运行结果:(成功按字母排序)

我们再用比较器排序来完成案例3

操作:在编辑比较器的时候添加条件的判断即可

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

		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",28,3));
		set.add(new Person("sdf",23,4));

		for (Object obj : set) {
			System.out.println(obj);
		}
	}

运行结果:(成功)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值