17.01 HashSet存储字符串并遍历
- Set并没有什么特殊的方法,我们主要学习它方法的实现(即如何保证元素不重复)
- HashSet类实现了Set接口
- Set集合是无索引,不可以重复,无序存取不一致
- 只要能用迭代器迭代的,就可以使用增强for循环遍历
17.02 HashSet存储自定义对象,保证元素唯一性
- 底层是用hashCode实现(hashCode是Object的方法)
17.03 HashSet保证对象的唯一性的原理
- 先调用hashCode方法,如果返回值一样,就去调用equals方法
- 让程序自动生成hashCode和equals方法
- hashCode返回的结果尽量不同,这样可以降低equals方法的调用,提高效率
- 我们做开发的时候,自动重写equals方法和hashCode方法就可以了
17.04 HashSet如何保证元素唯一性的原理
-
hashCode里面为什么定义31这个常量
- 31是一个质数,公约数少,重复的概率低
- 31不大不小
- 31这个数好算,是2的5次方减1,2左移5位减1
-
将自定义类的对象存入HashSet去重复
- 类中必须重写hashCode()和equals()方法
- hashCode():属性相同的对象返回值必须相同,属性不同的返回值尽量不同(提高效率)
- equals();属性相同返回true,属性不同返回false,返回false的时候存储
17.05 LinkedHashSet的概述和使用
- 底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
- 因为是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样
17.06 产生10个1-20的随机数(要求随机数不能重复)
package com.kevin.test;
import java.util.HashSet;
import java.util.Random;
public class Test1 {
/**
* @param args
*/
public static void main(String[] args) {
Random r = new Random();
HashSet<Integer> hs = new HashSet<>();
while(hs.size() < 10) {
hs.add(r.nextInt(20) +1 );
}
for (Integer integer : hs) {
System.out.println(integer);
}
}
}
17.07 练习一
- 使用Scanner从键盘读取一行输入,去掉其中重复字符,打印出不同的那些字符(顺序打印)
- aaaaddddgggghjjjj
package com.kevin.test;
import java.util.LinkedHashSet;
import java.util.Scanner;
public class Test2 {
/**
* @param args
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一行字符串:");
LinkedHashSet<Character> lhs = new LinkedHashSet<>();
String line = sc.nextLine();
char[] arr = line.toCharArray();
for (char c : arr) {
lhs.add(c);
}
for (Character ch : lhs) {
System.out.println(ch);
}
}
}
17.08 练习二
- 将集合中的重复元素去掉
package com.kevin.test;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
public class Test3 {
/**
* @param args
*/
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("b");
list.add("b");
list.add("b");
list.add("c");
list.add("c");
list.add("c");
list.add("c");
getSingle(list);
System.out.println(list);
}
public static void getSingle(List<String> list) {
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.addAll(list);
list.clear();
list.addAll(lhs);
}
}
17.09 TreeSet存储Integer类型的元素并遍历
- TreeSet集合是用来对元素进行排序的,同样它也可以保证元素的唯一
17.10 TreeSet存储自定义对象
- 实现某一个接口,就是增加特定的方法。
- 实现comparable接口,重写compareTo方法
- compare方法的返回值
- 返回0的时候:集合中只有一个元素
- 返回正数的时候:集合会正序存储
- 返回负数的时候:集合会倒序存储
17.11 TreeSet保证元素唯一和自然排序的原理和图解
- TreeSet底层是二叉树
- 小的存储在左边,大的存储在右边,相等就不存
- 重写比较的方法
17.12 TreeSet存储自定义对象并遍历练习
- 按照中文姓名去排序,底层是Unicode编码
17.13 按照姓名长度排序
- 使用length方法
17.14 TreeSet保证元素唯一和比较器排序的原理
- String类里面重写了compareTo方法,按字典顺序比较两个字符串,不考虑大小写
- comparator接口:比较器
17.15 TreeSet原理
- 特点
- TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列
- 使用方式
-
自然顺序(comparable)
- TreeSet类的add()方法中会把存入的对象提升为Comparable类型,存入的类必须实现Comparable接口,否则会报错
- 调用对象的compareTo方法和集合中的对象比较
- 根据compareTo()方法返回的结果进行存储
-
比较器顺序(Comparator)
- 创建TreeSet的时候可以指定一个Comparator
- 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
- add()方法内部会自动调用Comparator接口中的compare()方法排序
- 调用的对象时compare方法的第一个参数,集合中的对象时compare方法的第二个参数
-
两种方式的区别
- TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错ClassCastException)
- TreeSet如果传入Comparator,就优先按照Comparator进行排序
-
17.16 集合框架(练习1)
- 在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复
- 思路:因为String本身就具备比较功能,但是重复不会保留,所以我们用比较器
- 用匿名对象new Comparator<String>()
17.17 集合框架(练习2)
- 从键盘接收一个字符串,程序对其中所有字符进行排序,例如edcba程序打印abcde
- 思路:将字符串转换为字符数组,由于Character实现了comparable接口,所以还是要用比较器
1718 集合框架(练习3)
- 从键盘接收多个整数,直到输入quit时结束输入,把所有输入的整数倒序排列打印
- 8中基本数据类型包装类都实现了comparable接口
package com.kevin.test;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class Test6 {
/**
* @param args
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
int num = i2.compareTo(i1);
return num == 0 ? 1 : num;
}
});
while(true) {
String line = sc.nextLine();
if ("quit".equals(line)) {
break;
}
Integer i = Integer.parseInt(line);
ts.add(i);
}
for (Integer integer : ts) {
System.out.println(integer);
}
}
}
17.19 键盘录入学生信息,按照总分排序
- 分析
- 封装学生类,重写toString方法,方便打印
- 键盘录入需要Scanner
- 创建TreeSet集合对象,在TreeSet的构造函数中传入比较器,按照总分比较
- 录入5个学生,用集合的size是否小于5作为判断条件
- 将录入的字符串用逗号切割,会返回一个字符串数组,从第二开始转换为int数
- Student类
package com.kevin.bean;
public class Student {
private String name;
private int chinese;
private int math;
private int english;
private int sum;
public Student() {
super();
}
public Student(String name, int chinese, int math, int english) {
super();
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
this.sum = this.chinese + this.math + this.english;
}
public int getSum() {
return sum;
}
@Override
public String toString() {
return name + "," + chinese + "," + math + "," + english + "," + sum;
}
}
- Test7类
package com.kevin.test;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
import com.kevin.bean.Student;
public class Test7 {
/**
* @param args
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生成绩格式是:姓名,语文成绩,数学成绩,英语成绩");
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s2.getSum() - s1.getSum();
return num == 0 ? 1 : num;
}
});
while(ts.size() < 5) {
String line = sc.nextLine();
String[] arr = line.split(",");
int chinese = Integer.parseInt(arr[1]);
int math = Integer.parseInt(arr[2]);
int english = Integer.parseInt(arr[3]);
ts.add(new Student(arr[0], chinese, math, english));
}
System.out.println(" 排序后的学生信息:");
for (Student student : ts) {
System.out.println(student);
}
}
}













网友评论