Set集合概述及特点
A:Set集合概述及特点: 通过API查看即可
B: 案例演示: 无序(存储和取出的顺序)和唯一
案例一:
import java.util.Collection;
import java.util.HashSet;
public class SetDemo {
public static void main(String[] args) {
//Collection List 元素有序,允许元素重复
//Set 元素唯一 一个不包含重复元素的 collection
//HashSet 元素唯一,无序(存取顺序不一致)
//HashSet 底层数据结构是哈希表:是元素为链表的数组,具有链表和数组的特点 像新华字典(JDK1.7)
//HashSet()
//构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
HashSet<String> set = new HashSet<>();
set.add("林心如");
set.add("杨超越");
set.add("黎姿");
set.add("黎姿");
set.add("刘亦菲");
set.add("李易峰");
for (String s : set) {
System.out.println(s);
}
}
}
黎姿
林心如
杨超越
刘亦菲
李易峰
案例一:
import java.util.HashSet;
public class SetDemo2 {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>();
set.add(100);
// public HashSet() {
// map = new HashMap<>();
//}
//public boolean add (E e){
// return map.put(e, PRESENT) == null;
//}
//public V put (K key, V value){
// return putVal(hash(key), key, value, false, true);
//}
//static final int hash (Object key){
// int h;
// return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
//}
set.add(200);
set.add(100);
set.add(300);
set.add(90);
set.add(109);
for (Integer integer : set) {
System.out.println(integer);
}
}
}
结果:
100
200
90
300
109
HashSet保证元素唯一性
- HashSet 底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null
- 哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)
- 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,
然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。 - HashSet 集合判断两个元素相等的标准:
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。
案例一:
import java.util.Objects;
public class 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 int hashCode() {
// //张三 23 4+23*11
// //张三 23 4+23*11
// //张三 23 4+24
// //李四 24 3+24*11
//
// return this.name.hashCode() + this.age * 11;
//}
//
//@Override
//public boolean equals(Object obj) {
//
// System.out.println(this + "===" + obj);
// if (this == obj) {
// return true;
// }
// if (!(obj instanceof Student)) {
// return false;
// }
// Student student = (Student) obj;
//
// return this.name.equals(student.name) && this.age == student.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);
}
}
import java.util.HashMap;
import java.util.HashSet;
public class MyTest {
public static void main(String[] args) {
//HashSet集合能够保证元素的唯一性,是靠元素重写hashCode()方法和equals方法来保证的,如果元素不重写则无法保证
//HashSet 底层用的是HashMap来存的
Student s1 = new Student("王五", 25);
Student s2 = new Student("王五", 25);
Student s3 = new Student("王五", 25);
Student s4 = new Student("王五", 252);
Student s5 = new Student("王五2", 235);
Student s6 = new Student("王五3", 25);
Student s7 = new Student("王五4", 2665);
Student s8 = new Student("王五5", 285);
Student s9 = new Student("王五6", 285);
Student s10 = new Student("王五7", 255);
HashSet<Student> hashSet = new HashSet<>();
hashSet.add(s1);
hashSet.add(s2);
hashSet.add(s3);
hashSet.add(s4);
hashSet.add(s5);
hashSet.add(s6);
hashSet.add(s7);
hashSet.add(s8);
hashSet.add(s9);
hashSet.add(s10);
for (Student student : hashSet) {
System.out.println(student.getName() + "==" + student.getAge());
}
}
}
LinkedHashSet的概述和使用
数据结构 有两个 链表和哈希表
链表保证有序 哈希表保证元素唯一
A:LinkedHashSet的概述: 元素有序 , 并且唯一
B:案例演示: LinkedHashSet的特点
案例一:
// LinkedHashSet 底层数据结构是链表和哈希表,元素有序且唯一 ,链表保证了元素有序,哈希表保证了元素
import java.util.LinkedHashSet;
public class MyTest {
public static void main(String[] args) {
// LinkedHashSet 底层数据结构是链表和哈希表,元素有序且唯一 ,链表保证了元素有序,哈希表保证了元素
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("A");
linkedHashSet.add("B");
linkedHashSet.add("D");
linkedHashSet.add("E");
linkedHashSet.add("C");
linkedHashSet.add("E");
linkedHashSet.add("C");
linkedHashSet.add("E");
linkedHashSet.add("C");
for (String s : linkedHashSet) {
System.out.println(s);
}
}
}
结果:
A
B
D
E
C
## TreeSet概述及使用
A: TreeSet集合的特点:底层数据结构是二叉树,元素唯一,他最大的特点是能够对元素进行排序
排序:
a: 自然排序
b: 使用比较器排序
到底使用的是哪一种的排序取决于,构造方法.
TreeSet 排序方式分为 自然排序和比较器排序
具体用哪种排序,根据你使用的构造方法,用空参构造,那么就使用的是自然排序
有参构造,可以使用比较器来排序
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190719132157851.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xhbGFNYXJyeQ==,size_16,color_FFFFFF,t_70)
## TreeSet自然排序的原理和图解
A:画图演示: TreeSet保证元素唯一和自然排序的原理和图解
二叉树的数据结构 先存入一个树根 分两个叉
存储元素时 跟树根比较 小的放在左边 大的放在右边
如果相等就不存储
取的时候按照 左中右的顺序来取
案例一:
用自然排序对年龄进行排序,对名字进行排序
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190719132313962.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xhbGFNYXJyeQ==,size_16,color_FFFFFF,t_70)
package day20190719.study01.treeset;
import java.util.TreeSet;
/**
-
@description: treeset自然排序,使用类空参构造,对名字和年龄进行排序
-
@author: @李小白
-
@create: 2019-07-19 09:52
-
重写Comparable的compareTo方法进行排序
*/
public class Demo01 {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet<>();treeSet.add(new Student("张三士大夫士大夫", 23)); treeSet.add(new Student("张三是非得失", 23)); treeSet.add(new Student("李四大幅度发", 23)); treeSet.add(new Student("王五大幅度发", 20)); treeSet.add(new Student("周六的", 30)); treeSet.add(new Student("田七大幅度", 23)); treeSet.add(new Student("李白大幅度发", 33)); treeSet.add(new Student("刘星大幅度发", 63)); treeSet.add(new Student("夏雨", 78)); treeSet.add(new Student("张子豪", 53)); for (Student studnt : treeSet) { System.out.println(studnt); }
}
}
package day20190719.study01.treeset;
/**
-
@description: 学生共用类
-
@author: @李小白
-
@create: 2019-07-19 09:49
*/
public class Student implements Comparable{
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 int compareTo(Student student) {
//根据年龄大小进行排序
//int num=this.age-student.age;
//int num2=num0?this.name.compareTo(student.name):num;
//根据姓名长度进行排序
int num=this.name.length()-student.name.length();
int mun2=num0?this.name.compareTo(student.name):num;
//姓名长度如果一致,还要根据年龄大小进行排序
int nun3=mun2==0?this.age-student.age:mun2;
return nun3;
}
}
## TreeSet比较器排序的原理及代码实现
A:案例演示: TreeSet保证元素唯一和比较器排序的原理及代码实现
在创建TreeSet对象的时候,传递一个比较器对象
B: 按照年龄进行排序
案例一:
案例二:
用比比较器排序,对名字进行排序,年龄进行排序
package day20190719.study01.treeset;
import java.util.Comparator;
import java.util.TreeSet;
/**
-
@description: treeSet的比较排序
-
@author: @李小白
-
@create: 2019-07-19 10:09
*/
public class Demo02 {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet<>(new Comparator() {
@Override
public int compare(Student s1, Student s2) {
//根据年龄大小进行排序
//int num=s1.getAge()-s2.getAge();
//int num2=num0?s1.getName().compareTo(s2.getName()):num;
//根据姓名长短进行排序
int num1=s1.getName().length()-s2.getName().length();
int num2=num10?s1.getName().compareTo(s2.getName()):num1;
int num3=num1==0?s1.getAge()-s2.getAge():num2;
return num3;
}
});treeSet.add(new Student("张三士大夫士大夫", 23)); treeSet.add(new Student("张三是非得失", 23)); treeSet.add(new Student("李四大幅度发", 23)); treeSet.add(new Student("王五大幅度发", 20)); treeSet.add(new Student("周六的", 30)); treeSet.add(new Student("田七大幅度", 23)); treeSet.add(new Student("李白大幅度发", 33)); treeSet.add(new Student("刘星大幅度发", 63)); treeSet.add(new Student("夏雨", 78)); treeSet.add(new Student("张子豪", 53)); for (Student student : treeSet) { System.out.println(student); }
}
}
案例三:
new ArrayList<>()排序的另一种排序
import java.util.ArrayList;
import java.util.Comparator;
public class MyTest {
public static void main(String[] args) {
ArrayList integers = new ArrayList<>();
integers.add(21000000);
integers.add(2210);
integers.add(2130);
integers.add(2150);
integers.add(2150);
integers.add(21770);
integers.add(21550);
integers.sort(new Comparator() {
@Override
public int compare(Integer a, Integer b) {
return a-b;
}
});
System.out.println(integers);
}
}
import java.util.Arrays;
import java.util.Comparator;
public class MyTest2 {
public static void main(String[] args) {
Integer[] arr = {2, 4, 0, 1, 40, 24};
// Arrays.sort(arr);
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Integer a, Integer b) {
return -(a - b);
}
});
System.out.println(Arrays.toString(arr));
}
}
## 产生10个1-20之间的随机数要求随机数不能重复
A:案例演示
需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
并把最终的随机数输出到控制台。
选HashSet 可以不重复
选TreeSet 不重复还可以排序
分析:
a: 定义一个HashSet集合
b: 产生随机数,把随机数添加到集合中
c: 判断集合的长度,使用while循环实现
案例:
//A:
//案例演示
//需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
package day20190719.study01.treeset;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.TreeSet;
/**
- @description: treese用随机数编写
- @author: @李小白
- @create: 2019-07-19 10:34
- //A:
-
//案例演示
-
//需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
-
//并把最终的随机数输出到控制台。
-
//选HashSet 可以不重复
-
//选TreeSet 不重复还可以排序
*/
public class Demo03 {
public static void main(String[] args) {
Random random = new Random();//随机数
TreeSet integers = new TreeSet<>();//获取不能重复的
while (integers.size()<10) {//长度就是10
int i = random.nextInt(21);//获取1-20个随机数
integers.add(i);//输出不能重复的10个
}
System.out.println(integers);
}
}
键盘录入学生信息按照总分排序后输出在控制台
A:案例演示: 需求:键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
/**
* 步骤:
* a: 自定义一个学生类
* b: 创建一个TreeSet集合对象(使用比较器进行排序)
* c: 键盘录入学生的数据,然后把学生的数据封装成一个学生对象,把学生对象添加到集合中
* d: 遍历集合
*/
案例:
package day20190719.study01.treeset;
/**
-
@description: 定义学生的成绩和总分
-
@author: @李小白
-
@create: 2019-07-19 11:26
*/
public class Student02 {
private String name;
private int chineseScore;
private int mathScore;
private int englishScore;public Student02() {
}public Student02(String name, int chineseScore, int mathScore, int englishScore) {
this.name = name;
this.chineseScore = chineseScore;
this.mathScore = mathScore;
this.englishScore = englishScore;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public int getChineseScore() {
return chineseScore;
}public void setChineseScore(int chineseScore) {
this.chineseScore = chineseScore;
}public int getMathScore() {
return mathScore;
}public void setMathScore(int mathScore) {
this.mathScore = mathScore;
}public int getEnglishScore() {
return englishScore;
}public void setEnglishScore(int englishScore) {
this.englishScore = englishScore;
}
public int getTotalScore(){
return this.chineseScore+this.mathScore+this.englishScore;
}
}
package day20190719.study01.treeset;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/**
-
@description: 请输入三个学生的成绩并且打印出总分
-
@author: @李小白
-
@create: 2019-07-19 11:04
*/
public class Demo04 {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet<>(new Comparator() {
@Override
public int compare(Student02 s1, Student02 s2) {
int num=s2.getTotalScore()-s1.getTotalScore();
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});for (int i = 1; i <= 3; i++) { Student02 student = new Student02(); Scanner sc = new Scanner(System.in); System.out.println("请输入第"+i+"个学生的姓名"); String userName = sc.nextLine(); student.setName(userName); System.out.println("请输入第"+i+"个学生的语文成绩"); int ywScore = sc.nextInt(); student.setChineseScore(ywScore); System.out.println("请输入第"+i+"个学生的数学成绩"); int sxScore = sc.nextInt(); student.setMathScore(sxScore); System.out.println("请输入第"+i+"个学生的英语成绩"); int yyScore = sc.nextInt(); student.setEnglishScore(yyScore); treeSet.add(student); } System.out.println("序号\t姓名\t语文\t数学\t英语\t总分"); int index=1; for (Student02 stu : treeSet) { System.out.println(index + "\t\t" +stu.getName()+"\t\t"+ stu.getChineseScore() + "\t\t" + stu.getMathScore() + "\t\t" + stu.getEnglishScore() + "\t\t" + stu.getTotalScore()); index++; }
}
}
结果:
序号 姓名 语文 数学 英语 总分
1 李* 100 120 120 340
2 李** 100 100 100 300
3 章* 10 50 50 110
## set集合总结
//Set :底层数据结构是二叉树,元素唯一且可以对元素进行排序
// HashSet 底层数据结构是哈希表(数组+链表JDK1.7 JDK 数组+链表+二叉树) 元素无序(存取顺序不一致) 元素唯一
//唯一性要靠元素重写hashCode方法和equals方法来保证的
//重写hashCode是为了确定该元素在哈希表中的位置,我们合理重写hashCode可以减少碰撞
//重写equals是为了比较内容
// LinkedHashSet 底层数据结构是链表和哈希表 ,元素有序且唯一,链表保证了有序,哈希表保证了唯一
//TreeSet 底层数据结构是二叉树 他的特点唯一且能够对元素进行排序
//排序方式:自然排序和比较器排序
//如果用的无参构造,那么就使用自然排序,使用自然排序,对元素有要求,要求元素实现 Comparable接口重写compareTo方法
//根据此方法返回值的正负1、 0 来决定元素的排列位置
//使用有参构造,用的就是比较器,需要传入一个比较器 Comparator 重写里面的 compare 这个比较方法,根据此方法返回值的正1、 0 来决定元素的排列位置 Comparator比较器,其他一些类在调用sort()方法时也可以用