Set
- Set子类:HashSet — LinkedHashSet — TreeSet
顶层数据结构是哈希表(数组+链表 JDK1.7 数组+链表+二叉树——JDK1.8之后) - 概念:元素唯一
哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样)
HashSet
- 概念:元素唯一且无序———存取顺序不一致,集合元素可以是null
- HashSet 底层数据结构是哈希表 元素靠重写hashCode()和equals方法来保证唯一性
——————重写hashCode和equals方法
@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);
}
eg: HashSet<String> set = new HashSet<>();
set.add("余小晚");
set.add("肖正国");
set.add("张离");
set.add("陈山");
set.add("周海潮");
set.add("肖正国");
set.add("张离");
for (String s : set) {
System.out.println(s);————输出无序且仅一份
}
in.add(123);
in.add(456);
in.add(789);
in.add(000);
in.add(456);
in.add(789);
in.add(000);
for (Integer integer : in) {
System.out.println(integer);————输出无序且仅一份
}
自定义Student类型
eg: HashSet<Student> stu = new HashSet<Student>();
stu.add(new Student("小华",20));
stu.add(new Student("小明",21));
stu.add(new Student("小兰",22));
stu.add(new Student("小兰",22));
for (Student student : stu) {
System.out.println(student);————输出无序但不唯一————因为没有重写Hashcode和toString
}
LinkedHashSet
- 概念:元素唯一但有序————存取顺序一致
- LinkedHashSet 底层数据结构是链表(保证了有序)和哈希表(保证了唯一)
eg: LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("余小晚");
set.add("肖正国");
set.add("张离");
set.add("陈山");
set.add("周海潮");
set.add("肖正国");
for (String s : set) {
System.out.println(s);————输出有序且唯一
}
eg: 利用有参构造给ArratList集合去重复元素
ArrayList<Integer> list = new ArrayList<list>();
list.add(123);
list.add(456);
list.add(789);
list.add(456);
list.add(789);
LinkedHashSet<Integer> integers = new LinkedHashSet<>(list);
System.out.println(integers);————输出有序且唯一
TreeSet
- 概念:元素唯一且可对元素进行排序——————自然排序和比较器排序
自然排序:无参构造
- 自定义类中需要实现Comparable接口
- 需要重写该接口中得 compareTo()方法 —— 根据此方法 返回得正负 0 来决定元素在二叉树中的左右位置,返回0 就不往里面方法
- 报错原因:没有实现Comparable 接口 没有重写 compareTo()方法,无法判断在二叉树中节点的存放位置(左或者右)
- 二叉树:二叉树的数据结构 先存入一个树根 分两个叉 存储元素时 跟树根比较 小的放在左边 大的放在右边 如果相等就不存储 取的时候按照 左中右的顺序来取
自然排序——基本类
eg: TreeSet<Integer> set = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
set.add(111);
set.add(999);
set.add(555);
set.add(999);
set.add(222);
for (Integer integer : set) {
System.out.println(integer); ————输出:111 222 555 999
}
自然排序——自定义类
public class people implements Comparable<people> {
private String job;
private int age;
public people(){}
public people(String job,int age){
this.job = job;
this.age=age;
}
public String getJob() { return job; }
public void setJob(String job) { this.job = job; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public int compareTo(people o) {
int num = this.age-o.age;
int num1 = num==0?this.job.compareTo(o.job):num;
return num1;
}
}
eg public static void main(String[] args) {
TreeSet<people> set1 = new TreeSet<>();
set1.add(new people("医生",20));
set1.add(new people("老师",45));
set1.add(new people("警察",30));
set1.add(new people("律师",35));
for (people people : set1) {
System.out.println(people);
}
比较器排序:有参构造
比较器——————也是一个接口——Comparator
这个构造方法传入一个比较器(Comparetor 接口)重写这个接口中的compare()方法 根据此方法的返回值的正 负 0 来决定元素排列的左右顺序
new TreeSet(Comparator < ? super E > comparator)———构造一个新的空 TreeSet,它根据指定比较器进行排序。(TreeSet传入一个类Comparator的对象 建议用用匿名内部类)
- 重写Compare方法( ) compare(T o1, T o2—— 比较用来排序的两个参数
比较器排序——基本类型
eg: TreeSet<Integer> set = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
set.add(111);
set.add(999);
set.add(555);
set.add(999);
set.add(222);
for (Integer integer : set) {
System.out.println(integer);
}
比较器排序——自定义类型
import java.util.Comparator;
import java.util.TreeSet;
public class dmeo11 {
public static void main(String[] args) {
TreeSet<people1> set = new TreeSet<>(new Comparator<people1>() {
@Override
public int compare(people1 o1, people1 o2) {
int num = o1.age - o2.age;
int num1 = num == 0 ? o1.job.compareTo(o2.job) : num;
return num1;
}
});
set.add(new people1("医生",20));
set.add(new people1("老师",45));
set.add(new people1("警察",30));
set.add(new people1("律师",35));
for (people1 p1 : set) {
System.out.println(p1);
}
}
}
class people1 {
String job;
int age;
public people1() {
}
public people1(String job, int age) {
this.job = job;
this.age = age;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "people1{" +
"job='" + job + '\'' +
", age=" + age +
'}';
}
}
eg: Integer[] arr = {1999,18,2019,2020,2000,2008,2012,2};
Arrays.sort(arr, new Comparator<Integer>() {————-比较器也可用于排列数组
@Override
public int compare(Integer o1, Integer o2) {
return -(o1-o2);————从大到小排序
}
});
System.out.println(Arrays.toString(arr));——————输出:[2020, 2019, 2012, 2008, 2000, 1999, 18, 2]