set集合
Set接口:存储无序的,不可重复的数据,没有索引,不能使用普通for循环遍历,无下标,底层实际 上是HashMap(数组+链表+红黑树)
三个主实现类
🌟HashSet:作为Set接口的主要实现类,线程不安全,可以存储null值
🌟LinkedHashSet :作为HashSet的子类,遍历其内部数据,可以按照添加的顺序遍历 对于频繁 遍历操作,LinkedHashSet效率高于HashSet,用的不多,保证存入和取出的顺序一样
🌟TreeSet:可以按照添加对象的指定属性,进行排序
Hashset:
🔷HashSet:作为Set接口的主要实现类,线程不安全,可以存储null值
🔷HashSet是Set的主实现类,HashSet按hash算法来存储集合中的元素,具有很好的存储,查找, 删除性能
🍉HashSet具有以下特点
💫不能保证元素的排列顺序 💫HashSet不是线程安全的 💫集合元素可以为空
🍉底层数据结构是哈希表
🍉对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
🍉没有索引,所以不能使用普通for循环遍历
🍉由于是Set集合,所以是不包含重复元素的集合(去重)
set集合中使用自建的对象时需要注意的
🌟Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法
🌟要求:向Set中添 加的数据,其所有的类一定要重写hashCode()和equals()
🌟要求:重写hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码(哈 希值)
1 public class User {
2 private String name;
3 private int age;
4
5 public User() {
6 }
7
8 public User(String name, int age) {
9 this.name = name;
10 this.age = age;
11 }
12
13 public String getName() {
14 return name;
15 }
16
17 public void setName(String name) {
18 this.name = name;
19 }
20
21 public int getAge() {
22 return age;
23 }
24
25 public void setAge(int age) {
26 this.age = age;
27 }
28
29 @Override
30 public String toString() {
31 return "User{" +
32 "name='" + name + '\'' +
33 ", age=" + age +
34 '}';
35 }
36
37 @Override
38 //传入的对象默认为Object类型,此处涉及到多态
39 public boolean equals(Object o) {
40 //若参与比较的两个对象是同一个对象(地址值相同),直接返回true,只是为了提高代码执行效率
41 System.out.println("equals...................");
42 if (this == o) return true;
//若传入的参数o是null或者不是user类型,直接返回false,此处使用了反射技术来判断o是否是
user类型
43
44 if (o == null || getClass() != o.getClass()) return false;
45 //使用向下转型,将Object类型的o转化为user类型的o。这是因为在传入时使用了多态,
46 //多态不能使用子类特有的属性和方法
47 User user = (User) o;
48 //若两个对象的name和age都相同,返回true,否则返回false
49 return age == user.age &&
50 Objects.equals(name, user.name);
51 }
52
53 @Override
54 public int hashCode() {
55 return Objects.hash(name, age);
56 }
57 }
🔷TreeSet介绍:
🍉可以按照添加对象的指定属性,进行排序
1,向TreeSet中添加数据,要求是相同类的对象
2,两种排序方式:自然排序(Comparable)和定义排序(Comparator)
3,自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals();
4,定义排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals(); 默认使用自然排序
自然排序(对象两属性)
第一种compareto方法的格式
@Override
55 public int compareTo(Object o) {
56 if (o instanceof User){
57 User user = (User)o;
58 //return this.name.compareTo(user.name);
59
60 //如果想从大到小怎么做?
61 //return -this.name.compareTo(user.name);
62
63 //想添加进去,根据年龄来比较
64 int compare = -this.name.compareTo(user.name);
65 if (compare != 0){
66 return compare;
67 }else {
68 return Integer.compare(this.age,user.age);
69 }
70 }else {
71 throw new RuntimeException("输入的类型不匹配");
72 }
73
74 }
75 }
第二种compareto方法的格式
//按照姓名从大到小排序,按照年龄从小到大
2 @Override
3 public int compareTo(Object o) {
4 //instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例
5 //instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。
//instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回
boolean 的数据类型。
6
7 if (o instanceof User){
8 User user = (User)o;
9 //return this.name.compareTo(user.name); //从小到大
10 //return -this.name.compareTo(user.name); //从大到小
11 int compareTo = -this.name.compareTo(user.name);
12 if (compareTo != 0){
13 return compareTo;
14 }else {
15 return Integer.compare(this.age,user.age);
16 }
17 }else {
18 throw new RuntimeException("输入的类型不匹配");
19 }
20 }
对象类去实现compareto方法,剩下都是最基本的,调试类光添加数据以及输出
public class User implements Comparable
自定排序
public class Demo7 {
2 public static void main(String[] args) {
3 //Comparator接口
4 Comparator com = new Comparator() {
5 //按照年龄排序
6 @Override
7 public int compare(Object o1, Object o2) {
8 //前升序 后倒序
9 if (o1 instanceof User && o2 instanceof User){
10 User user1 = (User)o1;
11 User user2 = (User)o2;
12 //return Integer.compare(user1.getAge(),user2.getAge());
return Integer.compare(user2.getAge(),user1.getAge());
13
14 }else {
15 throw new RuntimeException("输入类型不匹配");
16 }
17 }
18 };
19
20 //TreeSet加参数:定义排序 不加就是自然排序
21 TreeSet set = new TreeSet(com);
22 set.add( new User("tom",19));
23 set.add( new User("Am",20));
24 set.add( new User("jk",18));
25 set.add( new User("Bm",16));
26 set.add( new User("Bm",17));
27
28 for (Object o : set) {
29 System.out.println("o = " + o);
30 }
31 }
32 }
作业案例
对象类
import java.util.Objects;
public class Woman{
private String name;
private int age;
private int score;
public Woman() {
}
public Woman(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
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;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Woman woman = (Woman) o;
return age == woman.age &&
score == woman.score &&
Objects.equals(name, woman.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, score);
}
@Override
public String toString() {
return name+"-"+age+"-"+score+" ";
}
}
执行类
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;
public class Demo14 {
//4,有5个学生对象,如下{"lucy", 28, 98},{"lily", 23, 97},
// // {"robt", 25, 100},{"wily", 15, 100},{"klin", 29, 93},
// //分别表示的是学生的姓名,年龄和分数.现要按学生成绩进行降序,
// // 如果成绩相同那么就按年龄进行升序
// //输出格式如下:wily-15-100 robt-25-100 lucy-28-98
// // lily-23-97 klin-29-93
public static void main(String[] args) {
TreeSet<Woman> set = new TreeSet<>(new Comparator<Woman>() {
@Override
public int compare(Woman o1, Woman o2) {
if (o1 instanceof Woman && o2 instanceof Woman){
Woman w1 = (Woman)o1;
Woman w2 = (Woman)o2;
int best = Integer.compare(o2.getScore(),o1.getScore());
int best2 = Integer.compare(o1.getAge(),o2.getAge());
best = best == 0 ? best2 : best;
return best;
}
else {
throw new RuntimeException();
}
}
});
set.add(new Woman("lucy", 28, 98));
set.add(new Woman("lily", 23, 97));
set.add(new Woman("robt", 25, 100));
set.add(new Woman("wily", 15, 100));
set.add(new Woman("klin", 29, 93));
Iterator<Woman> iterator = set.iterator();
while (iterator.hasNext()){
System.out.print(iterator.next());
}
}
}
对treeset的理解
两种比较方式小结
自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序
比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方 法,根据返回值进行排序
在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排 序
两种方式中关于返回值的规则
如果返回值为负数,表示当前存入的元素是较小值,存左边
如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
如果返回值为正数,表示当前存入的元素是较大值,存右边
总结
set:三无人员:无下标 无重复 无序
list:三有人员:有下标 有重复 有序
HashSet:一定要写equals和Hashcode;
TreeSet:只能添加相同的对象