【我的Java笔记】集合_Set

Set集合(接口)

1.概述:Set集合继承自Collection接口集合

2.Set集合特点:

(1)Set集合中储存的元素无序(存取不一致)

(2)Set集合中储存的元素唯一,不重复(Set接口底层数据是一个哈希表)

3.Set集合为接口,所以要靠子实现类HashSet,TreeSet来实现


注:Set集合和List集合的区别

(1)List集合元素可以重复,并且存在有序性(存储和取出一致)

(2)Set集合元素唯一不可重复,并且存在无序性(存储和取出不一致)



例:

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

public class SetDemo {
	public static void main(String[] args) {
		
		Set<String> set = new HashSet<String>();
		
		set.add("hello");
		set.add("hello");
		set.add("java");
		set.add("world");
		set.add("world");
		
		for(String str:set) {
			System.out.println(str);
		}
	}

}














HashSet集合(Set的子实现类)

1.概述:此类实现Set接口,底层由哈希表(HashMap实例)支持,不保证Set的迭代顺序恒久不变(无序输出

2.HashSet集合的add( ) 方法保证添加元素唯一性的方法:
(1)底层是依赖于双列集合HashMap<K,V>的 put (K key , V value) 来实现的,
 put (K key , V value) 底层又依赖于HashCode() 和 equals() 方法。
(2)当传递传递添加元素时的过程:
①先比较每一个元素对应的HashCode值是否相同
②若HashCode值相同,还会比较他们的equals () 方法
注:自定义对象添加至集合中则需重写hashcode() 和 equals() 方法


例1:HashCode
public class HashCodeDemo {
	
	public static void main(String[] args) {
		
		System.out.println("hello".hashCode());
		System.out.println("hello".hashCode());
		System.out.println("world".hashCode());
		System.out.println("world".hashCode());
		
		/**
		结果:
		99162322
		99162322
		113318802
		113318802	
		 */
	}
}





例2:自定义对象添加到集合中
import java.util.HashSet;

//测试类
public class HashSetDemo {
	
	public static void main(String[] args) {
		
		//创建一个HashSet集合对象
		HashSet<Student> hs = new HashSet<Student>() ;
		
		//创建学生对象
		Student s1 = new Student("高圆圆", 27) ;
		Student s2 = new Student("张三", 25) ;
		Student s3 = new Student("唐嫣", 26) ;
		Student s4 = new Student("邓超", 29) ;
		Student s5 = new Student("胡歌", 23) ;
		Student s6 = new Student("高圆圆", 27) ;
		
		//给集合中添加学生对象
		hs.add(s1) ;
		hs.add(s2) ;
		hs.add(s3) ;
		hs.add(s4) ;
		hs.add(s5) ;
		hs.add(s6) ;
		
		//增强for遍历
		for(Student s : hs){
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}
}


//学生类
class 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;
	}

	
	//给集合中添加自定义对象则需重写此类中的hashcode和equals()方法!
	@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;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) 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;
	}
	
}







LinkedHashSet集合(HashSet类的子类)

1.概述:具有可预知迭代顺序的Set接口的哈希表和链接列表实现

2.特点:
(1)由哈希表保证元素的唯一性
(2)由链接列表来保证元素的有序性

注:LinkedHashSet集合可以使Set集合变得有序


例:
import java.util.LinkedHashSet;

public class LinkedHashSetDemo {
	
	public static void main(String[] args) {
		
		//创建LinkedHashSet集合对象
		LinkedHashSet<String> link = new LinkedHashSet<String>();
		
		//给集合中添加元素
		link.add("hello") ;
		link.add("world") ;
		link.add("world") ;
		link.add("Java") ;
		link.add("Java") ;
		link.add("JavaWeb") ;
		link.add("JavaWeb") ;
		
		//遍历集合
		for(String str: link){
			System.out.println(str);
		}
	}
}















TreeSet集合(Set接口的子实现类)

1.概述:TreeSet集合底层是依赖于TreeMap的实例,而TreeMap依赖于红黑树结构实现

红黑树结构图解:



2.TreeSet集合两种排序方式(两中排序的不同取决于不同的构造方法):

(1)自然排序(无参构造:public TreeSet()根据其元素的自然顺序进行排序)

自定义对象则需实现Comparable<T>接口,重写public int compareTo()方法

注:Comparable接口后需接泛型

(2)比较器排序(构造方法:public TreeSet(Comparator<E> comparator)比较器排序)

自定义对象需重写Comparator接口中的public int compare(T  o1 , T  o2) 方法

注:一般采用匿名内部类的方式

Comparator接口后需加泛型


3.自然排序:

(1)例:集合存储Integer和String类型则比较元素第一位的自然顺序

import java.util.TreeSet;

public class TreeSetDemo {
	
	public static void main(String[] args){
		
		//创建TreeSet集合对象
		//构造方法:public TreeSet()	无参构造:根据其元素的自然顺序进行排序
		TreeSet<Integer> ts = new TreeSet<Integer>();
		
		//添加元素
		ts.add(20) ;
		ts.add(18) ;
		ts.add(23) ;
		ts.add(22) ;
		ts.add(17) ;
		ts.add(24) ;
		ts.add(19) ;
		ts.add(18) ;
		ts.add(24) ;
		
		//遍历集合
		for(Integer i : ts){
			System.out.print(i+ " ");
		}
	}
}





(2)TreeSet集合储存自定义对象并遍历:

此遍历方式实现了Comparable<T>接口,重写了compareTo(T  o)方法

元素唯一取决于compareTo方法返回值是否为0(为0则相同)!!


import java.util.TreeSet;

public class TreeSetDemo {
	
	public static void main(String[] args) {
		
		//创建TreeSet集合对象
		TreeSet<Student> ts = new TreeSet<Student>() ;
		
		//创建学生对象
		Student s1 = new Student("linqingxia", 28) ;
		Student s2 = new Student("fengqingy", 28) ;
		Student s3 = new Student("gaoyuanyuan", 27) ;
		Student s4 = new Student("liushishi", 26) ;
		Student s5 = new Student("wanglihong", 29) ;
		Student s6 = new Student("zhangguorong", 30) ;
		Student s7 = new Student("zhangguorong", 30) ;
		
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		ts.add(s7);
		
		//遍历
		for(Student s : ts){
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}	
}


//对于TreeSet集合存储自定义对象必须实现一个接口:compareable接口
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;
	}
	
	
	//重写compareTo()方法
	public int compareTo(Student s) {
		//排序的代码了,需要定义排序的条件
		//主要条件:按照学生的年龄从小到大进行排序
		int num =this.age - s.age ;//年龄从小到到 

		//当num==0认为年龄一样,年龄一样,不代表姓名的的内容是否相同,需要自己给出次要条件
		int num2 = num==0 ? this.name.compareTo(s.name): num ;
		return num2 ;
	}

}





4.比较器排序

依赖于构造方法:public TreeSet(Comparator<E> comparator)

注:Comparator作为参数进行传递,则需要该接口的自实现类来进行实现 


(1)方式一:自定义一个类来实现Comparator接口,作为子实现类

/*
 * 需求:按照学生姓名从小到大进行排序
 * 
 * 元素唯一性:取决于返回值是否为0
 * */

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

public class TreeSetDemo2 {
	
	public static void main(String[] args) {
		
		//创建TreeSet集合使用比较器进行给元素进行排序
		//public TreeSet(Comparator<E> comparator):有参构造
		TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;
		
		//创建学生对象
		Student s1 = new Student("gaoyuanyan", 27) ;
		Student s2 = new Student("liushishi", 22);
		Student s3 = new Student("fengqingy", 23) ;
		Student s4 = new Student("wuqilong", 35) ;
		Student s5 = new Student("gaoyuanyuan",27) ;
		Student s6 = new Student("zhangguorong",29) ;
		Student s7 = new Student("gaoyuanyuan",26) ;
		
		//添加元素
		ts.add(s1) ;
		ts.add(s2) ;
		ts.add(s3) ;
		ts.add(s4) ;
		ts.add(s5) ;
		ts.add(s6) ;
		ts.add(s7) ;
		
		//增强for遍历
		for(Student s : ts){
			System.out.println(s.getName()+"----"+s.getAge());
		}
	}
}


//MyComparatpr是Comparator接口的子实现类
class MyComparator implements Comparator<Student> {

	@Override
	public int compare(Student s1, Student s2) {
		//比较姓名长度是否一样
		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 ;
	}

}


//自定义类
class 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;
	}
	
}





(2)方式二:使用接口的匿名内部类来实现

匿名内部类格式:new 接口名或者类名(){
重写方法() ;

 } 


/*
 * 需求:按照学生姓名从小到大进行排序
 * 
 * 元素唯一性:取决于返回值是否为0
 * */

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

public class TreeSetDemo2 {
	
	public static void main(String[] args) {
		
		//创建TreeSet集合使用比较器进行给元素进行排序
		//public TreeSet(Comparator<E> comparator):有参构造
		/**
		 * 格式
		 * new 接口名或者类名(){
		 * 		重写方法() ;
		 * } 
		 */
		
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
				//比较姓名长度是否一样
				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("gaoyuanyan", 27) ;
		Student s2 = new Student("liushishi", 22);
		Student s3 = new Student("fengqingy", 23) ;
		Student s4 = new Student("wuqilong", 35) ;
		Student s5 = new Student("gaoyuanyuan",27) ;
		Student s6 = new Student("zhangguorong",29) ;
		Student s7 = new Student("gaoyuanyuan",26) ;
		
		//添加元素
		ts.add(s1) ;
		ts.add(s2) ;
		ts.add(s3) ;
		ts.add(s4) ;
		ts.add(s5) ;
		ts.add(s6) ;
		ts.add(s7) ;
		
		//增强for遍历
		for(Student s : ts){
			System.out.println(s.getName()+"----"+s.getAge());
		}
	}
}


//自定义类
class 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;
	}
	
}








课堂练习


/*
 * 需求:键盘录入五个学生的信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低进行输出
 * 
 * 分析:
 * 		(1)创建一个学生类,提供姓名以及各科成绩等成员变量
 * 		(2)创建TreeSet集合对象:TreeSet<Student>(Comparator<Student> com)
 * 		(3)条件分析:
 * 				主要:总分从高到低
 * 				次要:若总分相同,比较各科成绩是否相同
 * 		(4)键盘录入五个学生对象(for循环)
 * 		(5)输出
 * */

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

//测试类
public class TreeSetTest {

	public static void main(String[] args) {

		// 创建TreeSet集合对象
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

			public int compare(Student s1, Student s2) {
				// 比较总分
				int num1 = s2.getSum() - s1.getSum();

				// 总分相同,比较语文成绩
				int num2 = num1 == 0 ? s2.getChinese() - s1.getChinese() : num1;

				// 语文相同,则比较数学成绩
				int num3 = num2 == 0 ? s2.getMath() - s1.getMath() : num2;

				// 若以上条件都相同则比较名字内容是否相同
				int num4 = num3 == 0 ? s1.getName().compareTo(s2.getName()) : num3;

				return num4;
			}
		});

		System.out.println("请录入学生信息:");

		for (int i = 1; i <= 5; i++) {
			Scanner sc = new Scanner(System.in);

			// 录入学生信息
			System.out.println("请输入第" + i + "学生的姓名:");
			String name = sc.nextLine();
			System.out.println("请输入第" + i + "个学生的语文成绩:");
			String chineseScore = sc.nextLine();
			System.out.println("请输入第" + i + "个学生的数学成绩:");
			String mathScore = sc.nextLine();
			System.out.println("请输入第" + i + "个学生的英语成绩:");
			String englishScore = sc.nextLine();

			// 创建学生对象,将以上信息封装到学生对象中
			Student s = new Student(name, Integer.parseInt(chineseScore), Integer.parseInt(mathScore),
					Integer.parseInt(englishScore));
			// s.setName(name);
			// s.setChinese(Integer.parseInt(chineseScore));
			// s.setMath(Integer.parseInt(mathScore));
			// s.setEnglish(Integer.parseInt(englishScore));

			// 将学生对象添加至集合中
			ts.add(s);
		}

		System.out.println("学生信息总分从高到底排列顺序如下:");

		// 使用增强for循环遍历
		for (Student s : ts) {
			System.out.println(s);
		}

	}
}

// 学生类
class Student {
	private String name;
	private int chinese;
	private int math;
	private int english;

	Student() {

	}

	Student(String name, int chinese, int math, int english) {
		this.name = name;
		this.chinese = chinese;
		this.math = math;
		this.english = english;
	}

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

	public String getName() {
		return name;
	}

	public void setChinese(int chinese) {
		this.chinese = chinese;
	}

	public int getChinese() {
		return chinese;
	}

	public void setMath(int math) {
		this.math = math;
	}

	public int getMath() {
		return math;
	}

	public void setEnglish(int english) {
		this.english = english;
	}

	public int getEnglish() {
		return english;
	}

	// 获取总分的方法
	public int getSum() {
		return chinese + math + english;
	}

	public String toString() {
		return "[" + name + ":" + chinese + "," + math + "," + english + "]";
	}
}

/*
 * 测试:
 * 
 * 请录入学生信息: 
 * 请输入第1学生的姓名: 伊卡尔迪 
 * 请输入第1个学生的语文成绩: 78 
 * 请输入第1个学生的数学成绩: 87 
 * 请输入第1个学生的英语成绩: 90 
 * 请输入第2学生的姓名: 佩里西奇 
 * 请输入第2个学生的语文成绩: 67 
 * 请输入第2个学生的数学成绩: 98 
 * 请输入第2个学生的英语成绩: 90
 * 请输入第3学生的姓名: 坎德雷瓦 
 * 请输入第3个学生的语文成绩: 99 
 * 请输入第3个学生的数学成绩: 89 
 * 请输入第3个学生的英语成绩: 91
 * 请输入第4学生的姓名: 汉达诺维奇 
 * 请输入第4个学生的语文成绩: 90 
 * 请输入第4个学生的数学成绩: 90 
 * 请输入第4个学生的英语成绩: 89
 * 请输入第5学生的姓名: 加利亚迪尼 
 * 请输入第5个学生的语文成绩: 88 
 * 请输入第5个学生的数学成绩: 96 
 * 请输入第5个学生的英语成绩: 98
 * 学生信息总分从高到底排列顺序如下: 
 * [加利亚迪尼:88,96,98] 
 * [坎德雷瓦:99,89,91] 
 * [汉达诺维奇:90,90,89]
 * [伊卡尔迪:78,87,90] 
 * [佩里西奇:67,98,90]
 * 
 */


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值