Set接口
特点:
1.唯一
2.无序
3.可以存储null值,但是null值不能重复
package com.sxt.setdemo;
import java.util.HashSet;
import java.util.Set;
public class SetDemo01 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("abc");
set.add("efg");
set.add("abc");
set.add("hij");
set.add("abc");
set.add(null);
set.add(null);
System.out.println(set);
}
}
HashSet类
HashSet类
特点:
此类实现Set接口,由哈希表(实际为HashMap实例)支持。
对集合的迭代次序不作任何保证;
特别是,它不能保证订单在一段时间内保持不变。 这个类允许null元素
1.底层数据结构是哈希表结构,底层是通过HashMap实现
2.无序
3.允许null值
4.唯一
哈希算法原理:
1.哈希算法和对象本身有关
2.哈希算法和对象本身的hashCode有关
hashCode在没有重写hashCode方法的情况下就是地址值的一个转换值,可以理解为地址值
3.尽量保证哈希值唯一,但是不能绝对保证
哈希表结构原理:
哈希表结构如何保证元素无序的? 依赖的是随机的哈希算法产生的索引
哈希表结构如何保证元素唯一的? 依赖的是hashCode和equals方法
过程是:
首先比较两个元素的hashCode是否相等
相等
比较两个元素的equals方法是否相等
相等
表示同一个元素,就不存储的集合中
不相等
表示不是同一个元素,存储到集合中
不相等
说明两个元素不相等,直接存储
package com.
sxt.hashsetdemo;
import java.util.HashSet;
public class HashSetDemo01 {
public static void main(String[] args) {
HashSet<String> hs = new HashSet<String>();
hs.add("ab");
hs.add("ac");
hs.add("bc");
hs.add("ba");
hs.add("ba");
for (String s : hs) {
System.out.println(s);
}
}
}
随机获取6个20~30之间的数
package com.sxt.hashsetdemo;
import java.util.HashSet;
public class HashSetDemo01 {
public static void main(String[] args) {
HashSet<Integer> hs = new HashSet<Integer>();
while (hs.size() < 6) {
hs.add(getRandomNum(20, 30));
}
for (Integer integer : hs) {
System.out.println(integer);
}
}
public static int getRandomNum(int start, int end) {
return (int) (Math.random() * (end - start + 1) + start);
}
}
TreeSet
特点:
1.可排序
2.唯一
3.底层数据结构是二叉树
package com.sxt.treesetdemo;
import java.util.TreeSet;
/*
* TreeSet
*
* 特点:
* 1.可排序
* 2.唯一
* 3.底层数据结构是二叉树
*
* Integer
*/
public class TreeSetDemo01 {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<>();
ts.add(30);
ts.add(40);
ts.add(15);
ts.add(60);
ts.add(28);
ts.add(30);
ts.add(30);
ts.add(30);
for (Integer integer : ts) {
System.out.println(integer);
}
}
}
使用TreeSet存储学生对象
自然排序
package com.sxt.treesetdemo;
import java.util.TreeSet;
/*
* 使用TreeSet存储学生对象
*
* com.sxt.treesetdemo.Student cannot be cast to java.lang.Comparable
*
* public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
*/
public class TreeSetDemo02 {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>();
ts.add(new Student("zhangsan", 18));
ts.add(new Student("lisi", 20));
ts.add(new Student("wangwu", 30));
ts.add(new Student("haha", 30));
ts.add(new Student("hehe", 30));
ts.add(new Student("zhaoliu", 40));
ts.add(new Student("heihei", 30));
ts.add(new Student("sunqi", 25));
for (Student s : ts) {
System.out.println(s);
}
}
}
class Student implements Comparable<Student>{
private String name;
private Integer age;
public Student() {
super();
}
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student s) {
// 具体如何排序取决于需求
// 先按照年龄排序,如果年龄相同按照姓名排序
System.out.println("自然排序");
Integer num = this.getAge() - s.getAge();
// 年龄相同按照姓名排序
// int cmp = 0;
// if (num == 0) {
// String name1 = this.getName();
// String name2 = s.getName();
// cmp = name1.compareTo(name2);
// return cmp;
// } else {
// return num;
// }
int num2 = (num == 0) ? this.getName().compareTo(s.getName()) : num;
return num2;
}
}
比较器排序
package com.sxt.treesetdemo;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.TreeSet;
/*
* 比较器排序
* TreeSet(Comparator<? super E> comparator)
*
* 当自然排序和比较器排序同时存在的时候,比较器排序优先
*
*/
public class TreeSetDemo03 {
public static void main(String[] args) {
// TreeSet<Student> ts = new TreeSet<>(new ComparatorImpl());
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// System.out.println("匿名内部类比较器排序方式");
Collator collator = Collator.getInstance(Locale.CHINA);
int num1 = s1.getAge() - s2.getAge();
int num2 = (num1 == 0) ? collator.compare(s1.getName(), s2.getName()) : num1;
return num2;
}
});
ts.add(new Student("张三", 18));
ts.add(new Student("李四", 20));
ts.add(new Student("王五", 30));
ts.add(new Student("哈哈", 30));
ts.add(new Student("呵呵", 30));
ts.add(new Student("赵六", 40));
ts.add(new Student("嘿嘿", 30));
ts.add(new Student("孙七", 25));
for (Student s : ts) {
System.out.println(s);
}
}
}
class ComparatorImpl implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
System.out.println("比较器排序");
int num1 = s1.getAge() - s2.getAge();
int num2 = (num1 == 0) ? s1.getName().compareTo(s2.getName()) : num1;
return num2;
}
}
2.键盘录入5个学生信息(姓名,年龄,语文成绩,数学成绩,英语成绩),
按照总分从高到低输出到控制台
注:总分相同等情况下按照语文成绩排序,
其次是数学成绩、英语成绩、年龄、姓名
一个固定排序模板
package com.sxt.practice;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.TreeSet;
import com.sxt.treesetdemo.RandomValue;
public class TreeSetDemo04 {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 固定模板
Collator c = Collator.getInstance(Locale.CHINA);
double cmp = s1.getTotalScore() - s2.getTotalScore();
double cmp2 = (cmp == 0) ? (s1.getChineseScore() - s2.getChineseScore()) : cmp;
double cmp3 = (cmp2 == 0) ? (s1.getMathScore() - s2.getMathScore()) : cmp2;
double cmp4 = (cmp3 == 0) ? (s1.getEnglishScore() - s2.getEnglishScore()) : cmp3;
double cmp5 = (cmp4 == 0) ? (s1.getAge() - s2.getAge()) : cmp4;
double cmp6 = (cmp5 == 0) ? (c.compare(s1.getName(), s2.getName())) : cmp5;
return (cmp6 < 0) ? -1 : ( (cmp6 == 0) ? 0 : 1 );
}
});
for (int i = 0; i < 10; i++) {
String name = RandomValue.getChineseName();
int age = RandomValue.getRandomNum(18, 20);
double chineseScore = RandomValue.getRandomNum(88, 89);
double mathScore = RandomValue.getRandomNum(90, 91);
double englishScore = RandomValue.getRandomNum(95, 96);
Student s = new Student(name, age, chineseScore, mathScore, englishScore);
ts.add(s);
}
for (Student s : ts) {
System.out.println(s.getTotalScore() + " | " + s.getChineseScore()
+ " | " + s.getMathScore() + " | " + s.getEnglishScore()
+ " | " + s.getAge() + " | " + s.getName());
}
}
}
class Student {
private String name;
private Integer age;
private Double chineseScore;
private Double mathScore;
private Double englishScore;
public Student() {
super();
}
public Student(String name, Integer age, Double chineseScore, Double mathScore, Double englishScore) {
super();
this.name = name;
this.age = age;
this.chineseScore = chineseScore;
this.mathScore = mathScore;
this.englishScore = englishScore;
}
//计算总成绩
public Double getTotalScore() {
return chineseScore + mathScore + englishScore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getChineseScore() {
return chineseScore;
}
public void setChineseScore(Double chineseScore) {
this.chineseScore = chineseScore;
}
public Double getMathScore() {
return mathScore;
}
public void setMathScore(Double mathScore) {
this.mathScore = mathScore;
}
public Double getEnglishScore() {
return englishScore;
}
public void setEnglishScore(Double englishScore) {
this.englishScore = englishScore;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", chineseScore=" + chineseScore + ", mathScore=" + mathScore
+ ", englishScore=" + englishScore + ", getTotalScore()=" + getTotalScore() + "]";
}
}
LinkedHashSet类
特点:
底层数据结构是哈希表和链表
链表保证元素有序
哈希表保证元素唯一
package com.sxt.linkedhashsetdemo;
import java.util.LinkedHashSet;
public class LinkedHashSetDemo {
public static void main(String[] args) {
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.add("abc");
lhs.add("abc");
lhs.add("efg");
lhs.add("abc");
lhs.add("hij");
lhs.add("abc");
lhs.add("opq");
for (String s : lhs) {
System.out.println(s);
}
}
}