文章目录
-
-
- Set接口
-
- Set实现类之一: HashSet
- Set实现类之二: LinkedHashSet
- Set实现类之三: TreeSet
-
- TreeSet有两种排序方式:自然排序和定制排序
-
Set接口
要求:向Set中添加对象数据,必须重写equals和hashcode方法,且这两个方法要保持一致性
HashSet:线程不安全的,可以存储null值
LinkedHashSet:作为HashSet的子类,可以按照添加的顺序遍历
TreeSet:添加元素必须是同一个类new的对象,可根据对象的某些属性进行排序
Set实现类之一: HashSet
Set是无序不可重复的
- 无序性的体现:无序不代表随机性。其存储的数据在底层数组中的存储顺序不是按照数组索引递增的顺序进行存储而是按照数据所对应的hashcod值进行存储,从而体现出了无序性。
- 不可重复性的体现:保证添加的元素对象按照equals方法判断时,不能返回true,即相同元素只能添加一个。实际上就是要保证相同对象的hashcode也要相同,这就是为什么一般重写equals方法时都要重写hashcode方法
package com.senior.collectionuse;import org.junit.Test;import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Objects;/*** @author eden* @Description* @create projectTest-com.senior.collectionuse:2021-05-12-16:31* @since*/
public class SetInterface {
@Testpublic void setTest() {
HashSet hashSet = new LinkedHashSet();hashSet.add("123");hashSet.add(213);hashSet.add(null);hashSet.add(213);hashSet.add("eden");//如果User类中不重写equals和hashcode方法,那么以下两行代码认为是新建了两个对象//每个对象对应一个hashcode,由于hashcode不同因此认为是两个不一样的对象hashSet.add(new User("eden",11));hashSet.add(new User("eden",11));for (Object hash : hashSet) {
System.out.println(hash);}}}class User {
private String name;private int age;public User(String name, int age) {
this.name = name;this.age =age;}@Overridepublic String toString() {
return "User{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {
if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return age == user.age && Objects.equals(name, user.name);}//其底层demo-->hashCode有这样一句话// result = 31 * result + (element == null ? 0 : element.hashCode());@Overridepublic int hashCode() {
return Objects.hash(name, age);}
}
向HashSet中添加元素的过程:当向HashSet中添加元素A时,首先调用元素A所在类的hashcode方法,计算其对应的hash值,此hash值通过底层算法计算出其在HashSet底层数组中的存放位置,判断数组此位置上是否有元素,若没有,则直接添加进去,如果有元素B(或以链表形式存在多个元素),则比较元素A和B的hash值。若hash值不同,元素A也要添加进去,若相同,则调用元素A所在类的equals方法,如果返回为true,则元素A不添加,如果不同,则也要添加进去。
HashSet底层是数组+链表的结构
HashSet底层数组初始容量为16(JDK7), 当如果使用率超过0.75,(16*0.75=12)就会扩大容量为原来的2倍。 (16扩容为32, 依次为64,128…等)
Set实现类之二: LinkedHashSet
Set实现类之三: TreeSet
TreeSet:添加元素必须是同一个类new的对象
TreeSet有两种排序方式:自然排序和定制排序
//自然排序,实现Comparable
class User implements Comparable {
private String name;private int age;public User(String name, int age) {
this.name = name;this.age = age;}@Overridepublic String toString() {
return "User{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {
if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return age == user.age && Objects.equals(name, user.name);}//其底层demo-->hashCode有这样一句话// result = 31 * result + (element == null ? 0 : element.hashCode());@Overridepublic int hashCode() {
return Objects.hash(name, age);}//按照姓名排序@Overridepublic int compareTo(Object o) {
if (o instanceof User) {
User use = (User) o;int res = this.name.compareTo(use.name);if ( res!= 0) {
return res;} else {
return Integer.compare(this.age,use.age);}} else {
throw new RuntimeException("类型错误");}}
}class TreeSetTest {
public static void main(String[] args) {
TreeSet hashSet = new TreeSet();hashSet.add(new User("eden", 11));hashSet.add(new User("tom", 12));hashSet.add(new User("yyy", 13));hashSet.add(new User("jjj", 14));hashSet.add(new User("eden", 13));for (Object obj : hashSet) {
System.out.println(obj);}
// User{name='eden', age=11}
// User{name='eden', age=13}
// User{name='jjj', age=14}
// User{name='tom', age=12}
// User{name='yyy', age=13}}
}
定制排序,使用Comparator
@Testpublic void treesetTest2(){
//按照年龄Comparator com = new Comparator() {
@Overridepublic int compare(Object o1, Object o2) {
if(o1 instanceof User && o2 instanceof User){
User u1 = (User) o1;User u2 = (User) o2;return Integer.compare(u1.getAge(),u2.getAge());}else{
throw new RuntimeException("数据类型不匹配");}}};TreeSet hashSet = new TreeSet(com);hashSet.add(new User("eden", 11));hashSet.add(new User("tom", 12));hashSet.add(new User("yyy", 13));hashSet.add(new User("jjj", 14));hashSet.add(new User("eden", 13));for (Object obj : hashSet) {
System.out.println(obj);}
// User{name='eden', age=11}
// User{name='tom', age=12}
// User{name='yyy', age=13}
// User{name='jjj', age=14}}}
该博客图片来源于尚硅谷宋老师教学课件