Java集合3_HashSet
1 HashSet集合
1.1 HashSet存储字符串并遍历
* A:Set集合概述及特点
* Set集合,无索引,不可以重复,无序(存取不一致)
* B:案例演示
* HashSet存储字符串并遍历
package com.jhedu.day17; import java.util.ArrayList; import java.util.HashSet; public class Demo1_HashSet { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); //boolean b = list.add("d"); /** * 1. 在我们使用list集合的时候,add方法永远返回的是ture 有序,有索引 * 2. 在使用set集合的时候,add方法在添加重复元素时返回的是false 无序,无索引 * */ HashSet<String> hashSet = new HashSet<>(); boolean b = hashSet.add("wa"); hashSet.add("zf"); hashSet.add("qw"); hashSet.add("c"); hashSet.add("b"); hashSet.add("d"); hashSet.add("e"); hashSet.add("f"); System.out.println(hashSet.size()); System.out.println(hashSet); // 增强for循环遍历Hashset for(String s : hashSet){ System.out.println(s); } } }
1.1 HashSet存储自定义对象保证元素唯一性
一个类想拥有哪些特点,是有他的功能决定的。
* A:案例演示
* 存储自定义对象,并保证元素唯一性。
* 重写hashCode()和equals()方法
public static void demo2() { // HashSet存储自定义对象——学生类 /** * 当使用HashSet存储自定义对象时,必须重写equals方法和hashCode方法才能保证元素的唯一 */ HashSet<Student> hashSet = new HashSet<>(); hashSet.add(new Student("A",13)); // 1 hashSet.add(new Student("A",13)); // 2 A.equals(A); hashSet.add(new Student("B",36)); hashSet.add(new Student("C",31)); hashSet.add(new Student("D",23)); hashSet.add(new Student("C",34)); hashSet.add(new Student("C",34)); System.out.println(hashSet.size()); // for(Student s : hashSet){ System.out.print(s + " "); } }
1.1 HashSet如何保证元素唯一性的原理
* A:画图演示
* 画图说明比较过程
把对象往集合中添加的时候,会调用hashcode方法Hashcode值一样的时候才调用equals方法。要节约代码就让返回的hashCode尽量不同

* B:代码优化
* 为了减少比较,优化hashCode()代码写法。
* 最终版就是自动生成即可。
package com.jhedu.day17; import com.sun.xml.internal.ws.encoding.HasEncoding; import java.util.ArrayList; import java.util.HashSet; public class Demo1_HashSet { public static void main(String[] args) { demo2(); } public static void demo2() { // HashSet存储自定义对象——学生类 /** * 当使用HashSet存储自定义对象时,必须重写equals方法和hashCode方法才能保证元素的唯一 */ HashSet<Student> hashSet = new HashSet<>(); // hashCode执行的时间就是向集合中添加元素的时候 // equals方法执行的时间是只有hashCode值一样的时候,equals方法才会执行 // 当HashSet存储自定义对象时,必须重写equals方法和hashCode方法,才能保证元素唯一 hashSet.add(new Student("A",13)); // 1 hashSet.add(new Student("A",13)); // 2 A.equals(A); hashSet.add(new Student("A",13)); hashSet.add(new Student("A",13)); System.out.println(hashSet.size()); // 7 5 for(Student s : hashSet){ System.out.print(s + " "); } } public static void demo() { //boolean b = list.add("d"); /** * 1. 在我们使用list集合的时候,add方法永远返回的是ture 有序,有索引 * 2. 在使用set集合的时候,add方法在添加重复元素时返回的是false 无序,无索引 */ HashSet<String> hashSet = new HashSet<>(); boolean b = hashSet.add("wa"); hashSet.add("zf"); hashSet.add("qw"); hashSet.add("c"); hashSet.add("b"); hashSet.add("d"); hashSet.add("e"); hashSet.add("f"); System.out.println(hashSet.size()); // 7 4 System.out.println(hashSet); // 增强for循环遍历Hashset for(String s : hashSet){ System.out.println(s); } } }
* 1.HashSet原理
* 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
* 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
* 如果没有哈希值相同的对象就直接存入集合
* 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
* 2.将自定义类(如,Student,Person,Cat)的对象存入HashSet去重复
* 类中必须重写hashCode()和equals()方法
* hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
* equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储
1.1 LinkedHashSet的概述和使用
* A:LinkedHashSet的特点,
是唯一能保证怎么存就怎么取的set集合
* B:案例演示
* LinkedHashSet的特点
* 可以保证怎么存就怎么取
package com.jhedu.day17; import java.util.LinkedHashSet; public class Demo2_LinkedHashSet { public static void main(String[] args) { LinkedHashSet<String> linkSet = new LinkedHashSet<>(); /* LinkedHashSet可以保证元素唯一,并且可以保证有序(怎么存,就怎么取) */ linkSet.add("f"); linkSet.add("a"); linkSet.add("b"); linkSet.add("c"); linkSet.add("c"); linkSet.add("d"); linkSet.add("e"); // 增强for循环遍历LinkedHashSet for(String s :linkSet){ System.out.print(s + " "); } } }
2 TreeSet集合
2.1 TreeSet存储Integer类型的元素并遍历
* A:案例演示
* TreeSet存储Integer类型的元素并遍历
TreeSet集合是用来对元素进行排序的,同样他也可以保证元素的唯一
public static void demo() { /** * TreeSet会保证元素的唯一,并且会对元素进行排序 */ TreeSet<Integer> treeSet = new TreeSet<>(); treeSet.add(15); treeSet.add(56); treeSet.add(28); treeSet.add(16); treeSet.add(66); treeSet.add(1); treeSet.add(1); treeSet.add(66); treeSet.add(100); treeSet.add(0); System.out.println(treeSet.size()); System.out.println(treeSet); }
2.2 TreeSet存储自定义对象(CompareTo方法)重点和难点
package com.jhedu.day17; import java.util.TreeSet; public class Demo4_TreeSet { public static void main(String[] args) { demo2(); } public static void demo2() { String s1 = "b"; String s2 = "a"; s2.compareTo(s1); /** * 当两个对象相等时返回0 * 当调用对象小于被调用对象时,返回负数 * 当调用对象大于被调用对象时,返回正数 * * TreeSet存储对象的依据只会依赖与compareTo方法返回值。 */ // System.out.println(s2.compareTo(s1)); // 代表了String类重写compareTo方法 /** * TreeSet中增加自定义对象时,如果没有提供可比较的方法, * 就会抛出ClassCastException类型转换错误异常,解决方法是必须提供compareTo方法的重写 * 具体就实现Comparable接口。 */ TreeSet<Student> treeSet = new TreeSet<>(); treeSet.add(new Student("张三",23)); treeSet.add(new Student("李四",34));、 treeSet.add(new Student("周七",23)); treeSet.add(new Student("王五",56)); treeSet.add(new Student("赵六",18)); treeSet.add(new Student("张三",23)); //System.out.println(treeSet.size()); for(Student s: treeSet){ System.out.println(s); } } }
package com.se.bean; import java.util.Objects; public class Student implements Comparable<Student> { private String name; private int age; public Student() { } public Student(String name, int age) { 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 boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public int compareTo(Student o) { // int num = this.age - o.age; // return num==0?this.age-o.age:num; int num1 = this.name.compareTo(o.name); // name进行比较,返回int类型,0,1,-1 return num1 == 0 ? this.age - o.age : num1; // 如果名字相等返回0,再进行年龄比较,否则返回num1 } }
2.6 TreeSet原理
* 1.特点
* TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
* 2.使用方式
* a.自然顺序(Comparable)
* TreeSet类的add()方法中会把存入的对象提升为Comparable类型
* 调用对象的compareTo()方法和集合中的对象比较
* 根据compareTo()方法返回的结果进行存储
* b.比较器顺序(Comparator)
* 创建TreeSet的时候可以制定 一个Comparator
* 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
* add()方法内部会自动调用Comparator接口中compare()方法排序
* 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
* c.两种方式的区别
* TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
* TreeSet如果传入Comparator, 就优先按照Comparator
2.7 作业
2.7.1从键盘接收一个字符串, 程序对其中所有字符进行排序
例如键盘输入: helloitcast程序打印:acehillostt
package net.jhedu.fiften; import java.util.Comparator; import java.util.Scanner; import java.util.TreeSet; public class Demo1_HomeWorkF { /** * 从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt * 分析: * 1,键盘录入字符串,Scanner * 2,将字符串转换为字符数组 * 3,定义TreeSet集合,传入比较器对字符排序并保留重复 * 4,遍历字符数组,将每一个字符存储在TreeSet集合中 * 5,遍历TreeSet集合,打印每一个字符 */ public static void main(String[] args) { //1,键盘录入字符串,Scanner Scanner sc = new Scanner(System.in); System.out.println("请输入一个字符串"); String line = sc.nextLine(); //2,将字符串转换为字符数组 char[] arr = line.toCharArray(); //3,定义TreeSet集合,传入比较器对字符排序并保留重复 TreeSet<Character> ts = new TreeSet<>(new Comparator<Character>() { @Override public int compare(Character c1, Character c2) { //int num = c1 - c2; //自动拆箱 int num = c1.compareTo(c2); return num == 0 ? 1 : num;//相等的时候 返回1 保留相同的。 } }); //4,遍历字符数组,将每一个字符存储在TreeSet集合中 for(char c : arr) { ts.add(c); //自动装箱 } //5,遍历TreeSet集合,打印每一个字符 for(Character c : ts) { System.out.print(c); } } }
2.7.2在一个集合中存储了无序并且重复的字符串,
定义一个方法,让其有序(字典顺序),而且还不能去除重复
package com.jh.day29.set; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.TreeSet; public class Demo04_TreeSet { /** * 在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复 * * 分析: * 1,定义一个List集合,并存储重复的无序的字符串 * 2,定义方法对其排序保留重复 * 3,打印List集合 */ public static void main(String[] args) { //1,定义一个List集合,并存储重复的无序的字符串 ArrayList<String> list = new ArrayList<>(); list.add("aaa"); list.add("aaa"); list.add("ccc"); list.add("ddd"); list.add("fffffffffff"); list.add("heima"); list.add("itcast"); list.add("bbbb"); list.add("aaa"); list.add("aaa"); //2,定义方法对其排序保留重复 sort(list); // 3,打印List集合 System.out.println(list); } /* * 定义方法,排序并保留重复 * 分析: * 1,创建TreeSet集合对象,因为String本身就具备比较功能,但是重复不会保留,所以我们用比较器 * 2,将list集合中所有的元素添加到TrreSet集合中,对其排序,保留重复 * 3,清空list集合 * 4,将TreeSet集合中排好序的元素添加到list中 */ public static void sort(List<String> list) { //1,创建TreeSet集合对象,因为String本身就具备比较功能,但是重复不会保留,所以我们用比较器 TreeSet<String> ts = new TreeSet<>(new Comparator<String>() { @Override public int compare(String s1, String s2) { int num = s1.compareTo(s2); //比较内容为主要条件 return num == 0 ? 1 : num; //保留重复 } }); //2,将list集合中所有的元素添加到TrreSet集合中,对其排序,保留重复 ts.addAll(list); //3,清空list集合 list.clear(); //4,将TreeSet集合中排好序的元素添加到list中 list.addAll(ts); } }
2.7.3键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
/**
* * A:案例演示
* 需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
*
* 分析:
* 1,定义一个学生类
* 成员变量:姓名,语文成绩,数学成绩,英语成绩,总成绩
* 成员方法:空参,有参构造,有参构造的参数分别是姓名,语文成绩,数学成绩,英语成绩
* toString方法,在遍历集合中的Student对象打印对象引用的时候会显示属性值
* 2,键盘录入需要Scanner,创建键盘录入对象
* 3,创建TreeSet集合对象,在TreeSet的构造函数中传入比较器,按照总分比较
* 4,录入五个学生,所以以集合中的学生个数为判断条件,如果size是小于5就进行存储
* 5,将录入的字符串切割,用逗号切割,会返回一个字符串数组,将字符串数组中从二个元素转换成int数,
* 6,将转换后的结果封装成Student对象,将Student添加到TreeSet集合中
* 7,遍历TreeSet集合打印每一个Student对象
*/
package com.jh.day29.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; } public String toString() { return name + "," + chinese + "," + math + "," + english + "," + sum; } } public static void main(String[] args) { //2,键盘录入需要Scanner,创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入学生成绩格式是:姓名,语文成绩,数学成绩,英语成绩"); //3,创建TreeSet集合对象,在TreeSet的构造函数中传入比较器,按照总分比较 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; } }); //4,录入五个学生,所以以集合中的学生个数为判断条件,如果size是小于5就进行存储 while(ts.size() < 5) { //5,将录入的字符串切割,用逗号切割,会返回一个字符串数组,将字符串数组中从二个元素转换成int数, 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]); //6,将转换后的结果封装成Student对象,将Student添加到TreeSet集合中 ts.add(new Student(arr[0], chinese, math, english)); } //7,遍历TreeSet集合打印每一个Student对象 System.out.println("排序后的学生信息:"); for (Student s : ts) { System.out.println(s); } }

浙公网安备 33010602011771号