java ee 2019 11 14关于set集合

set


// 特点
// 不包含重复元素,由于他不能直接实例化
// 一般情况 使用子类实例化 hashset TreeSet
// HashSet集合
// 元素唯一的存储和取出不一致(无序),不保证顺序恒久不变
// 使用set集合存储字符串元素

package set;

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

public class SetDemo1 {

	public static void main(String[] args) {
		Set<String>set=new HashSet<String>();
			//给集合中添加元素
		//唯一  自己去重
		set.add("李小龙");
		set.add("成龙");
		set.add("周星驰");
		set.add("刘德华");
		set.add("李小龙");
		set.add("成龙");
		//增强for
		for(String s:set) {
			System.out.println(s);
		}

	}
周星驰
成龙
李小龙
刘德华
//去掉重复
//顺序不一致
}

//使用set集合存储自定义对象时Student类型(成员变量内容一样)
//认为是同一个人
//存储的是自定义对象,

HashSet

//HashSet集合底层add依赖于HashMap的put
//依赖于HashCode和equals()方法
//haseCode 保证唯一性(比较对象的地址值是否相同,
//如果地址值相同,还需要比较内容是否相同)
//equals():默认比较的地址值相同,要比较内容是否相同,
//必须在当前类中重写equals()方法
//set集合去重特性就是以上

import java.util.HashSet;
import java.util.Set;
public class SetDemo2 {
public static void main(String[] args) {
	//建立一个set集合对象
	Set<Student> set=new HashSet<Student>();
	//创建学生对象
	Student s1 = new Student("中国", 20) ;
	Student s2 = new Student("日本", 18) ;
	Student s3 = new Student("日本", 18) ;
	Student s4 = new Student("韩国", 25) ;
	Student s5 = new Student("韩国", 25) ;
	Student s6 = new Student("越南", 27) ;
	Student s7 = new Student("越南", 27) ;
	//给集合中添加
	set.add(s1) ;
	set.add(s2) ;
	set.add(s3) ;
	set.add(s4) ;
	set.add(s5) ;
	set.add(s6) ;
	set.add(s7) ;
	//遍历
	for(Student s: set) {
		System.out.println(s.getName()+"---"+s.getAge());
}
}
}

在用set存储自定义对象时
没有重写hashcode和equals会
日本—18
越南—27
越南—27
韩国—25
中国—20
日本—18
韩国—25
没有去重
重写后
越南—27
中国—20
日本—18
韩国—25
可以看到 顺序还是不能保障的

为什么Set集合存储的都是唯一的?
因为他的add() 添加方法
add()依赖于HashCode和equals
先比较哈希码值 值一样在比较内容 两个都一样就判定相等

String类型自动重写了


LinkedHashSet:

底层依赖于哈希表和链接列表实现
由哈希表保证元素唯一
由链表保证元素有序
特点:有序性和唯一性


Treeset集合:

// 基于TreeMap的实现 底层数据结构 根据不同的构造方法
//进行排序
//我的理解 既唯一 又可以自己构造排序
//排序两种方式 自然排序 构造器排序

自然排序

package set;

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

public class TreeSetDemo1 {
public static void main(String[] args) {
	//创建一个TreeSet集合对象
	Set<Integer> set=new TreeSet<Integer>();
	//添加元素
	set.add(20) ;
	set.add(18) ;
	set.add(23) ;
	set.add(22) ;
	set.add(17) ;
	set.add(24) ;
	set.add(19) ;
	set.add(18) ;
	set.add(24) ;
	//遍历集合
	for(Integer vv:set) {
		System.out.println(vv);
	}
}
17
18
19
20
22
23
24

}

这是因为Integer里面继承了自然排序 于是就有小到大排列了(默认升序)
再看TreeSet集合和自定义类
方式: 在子实现类重写Comparable

测试类

import java.util.TreeSet;

public class TreeSetDemo2 {

	public static void main(String[] args) {
		//创建Treeset集合对象
		TreeSet<Student> ss=new TreeSet<Student> ();
		//创建学生对象
		Student s1=new Student("张国荣",5);
		Student s2=new Student ("张杰",6);
		Student s3=new Student ("李",7);
		Student s4=new Student("樱木花道",8);
		Student s5=new Student ("迈克尔杰克逊",8);
		//添加
		ss.add(s1) ;
		ss.add(s2) ;
		ss.add(s3) ;
		ss.add(s4) ;
		ss.add(s5) ;
		//遍历
		for(Student  s:ss) {
			System.out.println(s.getName()+"--"+s.getAge());
		}

	}

}

自定义学生类

public class Student implements Comparable<Student>{
	private  String   name;
private   int age;
public Student() {
	super();
}
public Student(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 int compareTo(Student s) {
	//年龄从小到大
	//this 表示当前的
	//s.可以当成传入的
	//两个年龄的差值
	//后面比前面大
	//就是从小到大
	//this是对象  s是参数
	//如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。
	//如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。 //如果这两个字符串相等,则结果为 0
	int num = this.age -s.age ;
	//年龄一样 比较名字
	int num2 = (num==0)?(this.name.compareTo(s.name)) :num ;
	return num2;
}
  
张国荣--5
张杰--6--7
樱木花道--8
迈克尔杰克逊--8


}

年龄按从小到大排序
年龄一样比较名字

这里需要我们自己分析主要条件 次要条件
主要是重写这个Comparable方法

public class Student implements Comparable<Student>{
	
	private String name ;
	private int age ;
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(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 "Student [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int compareTo(Student s) {
		//主要条件:按照姓名的长度从小到大排序
		int num = this.name.length() - s.name.length() ;
		
		//次要条件:姓名长度一样,姓名内容不一定相同
		int num2 = (num==0)?(this.name.compareTo(s.name)):num ;
		
		//如果姓名长度一样,姓名内容也一样,年龄可能不同
		int num3 = (num2==0)?(this.age-s.age):num2;
		return num3;
	}
	
	
}

这里就写出了三个条件
有时给出了主要 次要自己写


TreeSet中构造器排序 ------Comparator

方式(1)和自然排序一样
方式(2)匿名内部类-------在内部类中重写方法
import java.util.TreeSet;

//构造器排序
//使用比较器排序
//主要条件按姓名的长度从小到大排序

方式(1)

首先给一个学生类

public class Student{
	
	private String name ;
	private int age ;
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(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 "Student [name=" + name + ", age=" + age + "]";
	}
	
	
}

测试类

public class TreeSetDemo3 {

	public static void main(String[] args) {
		//创建一个TreeSet集合对象,有参构造方式
		TreeSet<Student> tt=new TreeSet<Student> (new MyComparator));
		//创建学生对象
		Student s1 = new Student("zhangguorong", 20) ;
		Student s2 = new Student("wanglihong", 20) ;
		Student s3 = new Student("wenzhang", 20) ;
		Student s4 = new Student("zhangguorong", 28) ;
		Student s5 = new Student("gaoyuanyuan", 25) ;
		Student s6 = new Student("zhaoyouting", 29) ;
		Student s7 = new Student("zhaoyouting", 35) ;
		Student s8 = new Student("liushishi", 34) ;
		Student s9 = new Student("wuqilong", 43) ;
		Student s10 = new Student("wenzhang", 27) ;
		//添加集合中
		tt.add(s1) ;
		tt.add(s2) ;
		tt.add(s3) ;
		tt.add(s4) ;
		tt.add(s5) ;
		tt.add(s6) ;
		tt.add(s7) ;
		tt.add(s8) ;
		tt.add(s9) ;
		tt.add(s10) ;
		for (Student  s:tt) {
		System.out.println(s.getName()+"------"+s.getAge());
	}

	}
	wenzhang------27
wuqilong------43
liushishi------34
wanglihong------20
gaoyuanyuan------25
zhaoyouting------29
zhaoyouting------35
zhangguorong------20
zhangguorong------28

}

定义子实现类比较器接口

import java.util.Comparator;

public class MyComparator  implements Comparator<Student>{

	
		

	

@Override
	public int compare(Student s1, Student s2) {
		
		s1----自然排序的this---对象
		s2-----自然排序的S------参数
		//主要条件:按姓名的长度从小到大
		int num=s1.getName().length()-s2.getName().length();
	//次要条件:姓名长度一样,比较内容
		int num2=(num==0)?(s1.getName().compareTo(s2.getName())):num;
		//内容一样,不一定年龄不一样
		int num3=(num==0)?(s1.getAge()-s2.getAge()):num2;
		return num3;
	}

	}

这要写一个比较器接口
方法二就比较简便
使用匿名内部类(推荐使用)

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

public class TreeSetDemo4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	
			//创建一个TreeSet集合对象
			TreeSet<Student> tt=new TreeSet<Student> (new Comparator<Student>() {

				@Override
				public int compare(Student s1, Student s2) {
					// TODO Auto-generated method stub
					//s1----->刚才使用自然排序里面 this 
					//s2----->刚才使用自然排序里面的s
					//主要条件:按姓名的长度从小到大排序
					int num=s1.getName().length()-s2.getName().length();
					//次要条件  姓名长度一样 内容不一定一样
					int num2=(num==0)?(s1.getName().compareTo(s2.getName())):num;
					//内容一样,不一定年龄一样
					int num3 = (num2==0)?(s1.getAge()-s2.getAge()):num2 ;
					return num3;
					
					
					
					
				}
				});
			
			//创建学生对象
			Student s1 = new Student("zhangguorong", 20) ;
			Student s2 = new Student("wanglihong", 20) ;
			Student s3 = new Student("wenzhang", 20) ;
			Student s4 = new Student("zhangguorong", 28) ;
			Student s5 = new Student("gaoyuanyuan", 25) ;
			Student s6 = new Student("zhaoyouting", 29) ;
			Student s7 = new Student("zhaoyouting", 35) ;
			Student s8 = new Student("liushishi", 34) ;
			Student s9 = new Student("wuqilong", 43) ;
			Student s10 = new Student("wenzhang", 27) ;
			//添加集合中
			tt.add(s1) ;
			tt.add(s2) ;
			tt.add(s4) ;
			tt.add(s5) ;
			tt.add(s6) ;
			tt.add(s7) ;
			tt.add(s8) ;
			tt.add(s9) ;
			tt.add(s10) ;
			for (Student  s:tt) {
			System.out.println(s.getName()+"------"+s.getAge());
	}
wenzhang------27
wuqilong------43
liushishi------34
wanglihong------20
gaoyuanyuan------25
zhaoyouting------29
zhaoyouting------35
zhangguorong------20
zhangguorong------28

}
}

总结
comparable
在子实现类中重写方法
继承Comparable接口 comparable不用写
子实现类重写方法

Comparator
(1)

自定义类不做任何操作
写一个comparator接口 接口中重写方法
测试类中实现接口

(2)
匿名内部类
(推荐使用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值