set是接口,继承collection,set下有hashset、treeset、linkedhashset。以下介绍三种的特点:
- Set内的元素无序,且唯一。
- Hashset的特点
顶层数据结构是哈希表,元素无序且唯一,但是是怎么保证元素的唯一性呢?
import java.util.HashSet;
public class test {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("aaa");
set.add("bbb");
set.add("ccc");
for (String s : set) {
System.out.println(s);
}
}
}
结果是:
aaa
ccc
bbb
HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。
import java.util.HashSet;
public class test1 {
public static void main(String[] args) {
HashSet<Student> set = new HashSet<>();
set.add(new Student("刘洋",18));
set.add(new Student("李洋",19));
set.add(new Student("王洋",20));
set.add(new Student("赵洋",21));
set.add(new Student("张洋",22));
set.add(new Student("刘洋",18));
set.add(new Student("李洋",19));
for (Student s : set) {
System.out.println(s.getName()+"==="+s.getAge());
}
}
}
//学生类
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 int hashCode() {
return this.name.hashCode()+age*10;
}
@Override
public boolean equals(Object obj) {
if (this==obj){
return true;
}
if (!(obj instanceof Student)){
return false;
}
Student stu= (Student) obj;
return this.age==stu.age&&this.name.equals(stu.name);
}
}
- LinkedHashSet的特点
底层数据结构是链表和哈希表:
①由链表保证元素有序
②由哈希表保证元素唯一
import java.util.ArrayList;
import java.util.LinkedHashSet;
public class test3 {
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("aaa");
set.add("bbb");
set.add("ccc");
for (String s : set) {
System.out.println(s);
}
System.out.println("----------------");
ArrayList<String> strings = new ArrayList<>();
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
LinkedHashSet<String> strings1 = new LinkedHashSet<>(strings);
System.out.println(strings1);
}
}
-
TreeSet集合的特点:
元素唯一,并且可以对元素进行排序。
排序方式有两种:
①自然排序:自然排序,你使用得是无参构造,自然排序,对排序得元素有要求,要求元素必须实现一个Comparable接口,重写该接口中的ComparableTo方法,根据此方法返回得正负0来决定元素在二叉树中的左右位置,返回0就不往里面方法。
②比较器排序:
1)接口 Comparator 比较器
2)compare(T o1, T o2),比较用来排序的两个参数
3)TreeSet(Comparator < ? super E > comparator),构造一个新的空 TreeSet,它根据指定比较器进行排序。
保证唯一性:
保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等则不重复存储。 -
TreeSet保证元素唯一和自然排序
import java.util.TreeSet;
public class test2 {
public static void main(String[] args) {
//自然排序
// Comparable 接口,重写该接口中得 compareTo()方法,根据此方法 返回得正负 0 来决定元素在二叉树中的左右位置,返回0 就不往里面方法
//按照年龄、姓名排序 先比较年龄,年龄相同比较姓名
TreeSet<Student> set = new TreeSet<>();
set.add(new Student("刘洋2",18));
set.add(new Student("李洋",19));
set.add(new Student("王洋",20));
set.add(new Student("赵洋",21));
set.add(new Student("张洋",22));
set.add(new Student("刘洋1",18));
set.add(new Student("李洋",19));
for (Student s : set) {
System.out.println(s);
}
}
}
//学生类
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 int compareTo(Student o) {
int num = this.age-o.age;
int num2=(num==0)?this.name.compareTo(o.name):num;
return num2;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
结果:
Student{name='刘洋1', age=18}
Student{name='刘洋2', age=18}
Student{name='李洋', age=19}
Student{name='王洋', age=20}
Student{name='赵洋', age=21}
Student{name='张洋', age=22}
- TreeSet保证元素唯一和比较器排序
import java.util.Comparator;
import java.util.TreeSet;
public class test4 {
public static void main(String[] args) {
//MyCompareTor myCompareTor = new MyCompareTor();
//TreeSet<Student> set = new TreeSet<>(myCompareTor);
//匿名内部类
TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//根据年龄排序
int num=s1.getAge()-s2.getAge();
int num2=(num==0)?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
set.add(new Student("刘洋2",18));
set.add(new Student("李洋",19));
set.add(new Student("王洋",20));
set.add(new Student("赵洋",21));
set.add(new Student("张洋",22));
set.add(new Student("刘洋1",18));
set.add(new Student("李洋",19));
for (Student student : set) {
System.out.println(student);
}
}
}
class MyCompareTor implements Comparator<Student>{
@Override
public int compare(Student s1, Student s2) {
int num=s1.getAge()-s2.getAge();
int num2=(num==0)?s1.getName().compareTo(s2.getName()):num;
return num2;
}
}
结果:
Student{name='刘洋1', age=18}
Student{name='刘洋2', age=18}
Student{name='李洋', age=19}
Student{name='王洋', age=20}
Student{name='赵洋', age=21}
Student{name='张洋', age=22}
- 练习1:产生10个1-20之间的随机数要求随机数不能重复
import java.util.HashSet;
import java.util.Random;
public class test5 {
public static void main(String[] args) {
//产生10个1-20之间的随机数要求随机数不能重复
/*
* 1.建立一个HashSet集合
* 2.产生随机数,添加到集合中
* 3.根据集合长度,实现循环*/
HashSet<Integer> integers = new HashSet<>();
Random random = new Random();
while (integers.size() < 10) {
int num = random.nextInt(20) + 1;
integers.add(num);
}
System.out.println(integers);
}
}
- 练习2:键盘录入学生信息按照总分排序后输出在控制台
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class test6 {
public static void main(String[] args) {
//需求:键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
/**
* 步骤:
* a: 自定义一个学生类
* b: 创建一个TreeSet集合对象(使用比较器进行排序)
* c: 键盘录入学生的数据,然后把学生的数据封装成一个学生对象,把学生对象添加到集合中
* d: 遍历集合
*/
TreeSet<Student> students = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//按照总分排序
int num = s1.getTotal()-s2.getTotal();
return num;
}
});
System.out.println("请录入成绩");
for (int i = 0; i <3 ; i++) {
Scanner scanner = new Scanner(System.in);
System.out.println("请录入第"+(i+1)+"个学生的姓名");
String name = scanner.next();
System.out.println("请录入第"+(i+1)+"个学生的语文成绩");
int chinese = scanner.nextInt();
System.out.println("请录入第"+(i+1)+"个学生的数学成绩");
int math = scanner.nextInt();
System.out.println("请录入第"+(i+1)+"个学生的英语成绩");
int english = scanner.nextInt();
Student student = new Student(name, english, chinese, math);
students.add(student);
}
System.out.println("序号\t姓名\t语文\t数学\t英语\t总分");
for (Student stu : students) {
System.out.println(stu.getName()+"\t\t" +stu.getChinese()+"\t\t"
+stu.getEnglish()+"\t\t" +stu.getMath()+"\t\t" +stu.getTotal());
}
}
}
//学生类
public class Student {
private String name;
private int english;
private int chinese;
private int math;
private int total;
public Student() {
}
public Student(String name, int english, int chinese, int math) {
this.name = name;
this.english = english;
this.chinese = chinese;
this.math = math;
this.total = total;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getTotal() {
return this.chinese+english+math;
}
}