带妹学Java第十二天(至集合Set接口——TreeSet)

重点

1.Set接口的特点讲解

Set:接口
1.一个不包含重复元素的 collection。
2.最多包含一个 null 元素
3.一般使用它实现类:HashSet,LinkedHashSet,TreeSet
4.Set集合存和取的顺序不一样,【每一次取的顺序都可能不一样】

List:接口
1.List是可存储相同元素
2.List存的取的元素顺序是一样

2.HashSet

1.此类实现 Set 接口
2.由哈希表(实际上是一个 HashMap 实例)支持。
3.它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
4.此类允许使用 null 元素。

Set遍历一、增强for循环
Set遍历二、迭代器

3.hashCode与equals的原理

1 .通过set集合的add方法添加元素时,内部会调用hashcode和equals方法
2. 如果比较的hashcode的值是一样的话,会调用equals方法,equals方法返回true,就不存元素,返回false就存元素
3. 如果比较的hashcode的值不一样,就直接存元素

4.hashCode与equals的优化

  • 优化:
    Person
    -name
    -age
  • 1.如果名字不一样,就不需要调用equals方法,从而优化代码
  • return this.name.hashCode()
  • 2.hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
    return this.name.hashCode() + this.age;

5.LinkedHashSet

LinkedHashSet是HashSet的子类
LinkedHashSet 存和取的顺序是一样

6.TreeSet

TreeSet是一种能排序集合
默认情况下,TreeSet存Integer时,由小到大排序
默认情况下,TreeSet存String时,字母的由小到大排序
Integer和String这两个类都内部实现了comparable接口

7.TreeSet保存自定义对象

自定义对象必须实现comparable接口?
实现这个接口的目的是告诉TreeSet你的元素的排序规则
实现了comparable接口的类,要实现compareTo方法
compareTo方法:
0-只存一个元素,第一个元素
-1:存的顺序倒序
1:存的顺序正序

8.TreeSet排序的原理

TreeSet是使用二叉权存数据
0:不存
负数:存在左边
正数:存在右边

练习题

1.HashSet存储自定义对象保证元素唯一性

//思路:需要重写hashCode()和equals()方法

public int hashCode() {
		// TODO Auto-generated method stub
		System.out.println(this.name + ":" + this.name.hashCode());
		*//**
		 * 优化:
		 * 1.如果名字不一样,就不需要调用equals方法,从而优化代码
		 *   return this.name.hashCode()
		 * 2.hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
		 *//*
		return this.name.hashCode() + this.age;
	}
	
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		Person other = (Person) obj;
		System.out.println(this.name + "....比较...." + other.name);
		return this.age == other.age && this.name.equals(other.name);
  • 熟悉原理后,可用快捷键自动生成。

2.产生10个1-20之间的随机数要求随机数不能重复

  • 关键:HashSet,Random,While(true)
public static void main(String[] args) {
		
		//思路:生成0-20的随机数,判断不为0才添加,判断集合大小为10才退出循环
		Random random = new Random();
	
		Set<Integer> set = new HashSet<Integer>();
		
		while(true){
			int i = random.nextInt(21);//0~20 
			if (i!=0) {
				set.add(i);
			}
			if (set.size()==10) {
				break;
			}
		}
		
		for(Integer ig : set){
			System.out.println(ig);
		}
	}

3.从键盘读取一行输入,去除重复的字符

public static void main(String[] args) {
		System.out.println("请输入字符串:");
		Scanner scanner = new Scanner(System.in);
		String str = scanner.next();
		System.out.println(str);
		Set<Character> cha = new HashSet<Character>();
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			//System.out.println(c);
			cha.add(c);
		}
		System.out.println(cha);
		
		for(Character ch : cha){
			System.out.println(ch);
		}
	}

4.//将List集合中的重复元素去掉(set实现)

//思路:遍历List集合的每一个元素将它添加到Set集合中,Set然后会自动排除重复的元素(字符串)

public static void main(String[] args) {
		//将List集合中的重复元素去掉(set实现)
		List<Integer> list = new ArrayList<Integer>();
		list.add(12);
		list.add(15);
		list.add(16);
		list.add(16);
		System.out.println("list:"+list);
		
		Set<Integer> set = new HashSet<Integer>();
		for(Integer i : list){
			set.add(i);
		}
		
		System.out.println("set:"+set);
		
	}

5.Person 要按年龄和名字进行排序

@Override
	public int compareTo(Person other) {
		// TODO Auto-generated method stub
		//1.按年龄的由小到大排序
		int num =  this.age - other.age;
		System.out.println(this.name + "..比较..." + other.name + " 年龄差:" + num);
		
		//if(num == 0) num = 1;
		
		//2.如果年龄一样,根据名字排序 [字符串一样,比较的结果也是0]
		//String s;
		if(num == 0){
			num = this.name.compareTo(other.name);
		}
		
		return num;
	}

6. Student 要按名字的长度,名字和年龄进行排序

public class Demo04 {
	public static void main(String[] args) {
		//TreeSet存储自定义对象并遍历,按照姓名长度、字母、年龄排序
		Set<Student> students = new TreeSet<Student>();
		students.add(new Student("asd", 12));
		students.add(new Student("cbdh", 22));
		students.add(new Student("csdf", 32));
		students.add(new Student("asd", 12));
		System.out.println(students);
		
		for(Student stu : students){
			System.out.println(stu);
		}
	}
}

class Student implements Comparable<Student>{
	private String name;
	private int age;
	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int compareTo(Student other) {
		// TODO Auto-generated method stub
		//1.按照姓名长度
		int i = this.name.length() - other.name.length();
		//2.字母排序
		if(i==0){
			i = this.name.compareTo(other.name);
		}
		//3.年龄排序
		if (i==0) {
			i= this.age - other.age;
		}
		return i;
	}
	
}

面试题

1.你在开发中经常使用Java的哪些包?

1.java.util包,这个包有很集合框架:List/Set/Map

2.为什么自动生成hashcode的时有个31的数

①31是一个质数,质数是能被1和自己本身整除的数,没有公约数
②3l这个数既不大也不小,
■大的话可能超过int的取值范围
■小的话,相同机率出现比较多
③31这个数好算,2的五次方-1,1向左移动5位 1<<5

总结

通过对集合Set接口的3个实现类HashSet、LinkedHashSet 、TreeSet的学习,知道了Set集合的很多细节的地方,比如Set集合不能存重复的元素,存和取的顺序也不同,对于自定义对象想要保证元素的唯一性,需要自己重写hashCode和equals方法,当了解到了他们的实现原理时,可以对他们调优。实际开发中,可以利用快捷键自动生成自定义对象的hashCode和equals方法。然后就是LinkedHashSet,它是HashSet的子类,特点时存和取的顺序是一样。而TreeSet是一种能排序集合,内部实现了comparable接口。使用自定义对象时,要实现comparable接口,重写compareTo()方法。坚持敲代码!

发布了24 篇原创文章 · 获赞 4 · 访问量 614

猜你喜欢

转载自blog.csdn.net/qq_43488797/article/details/103817760