目录
1. Set特性:
3. TreeSet
3.1定制排序(比较器排序)
3.2自然排序:
4. LinkedHashSet
在日常开发中不可避免会遇到需要去重,或者查找重复元素,下面给介绍一种效率比较高的方法,时间复杂度为O(n)
1. Set特性:
①不允许出现重复元素;
②集合中的元素位置无顺序;
③有且只有一个值为null的元素。
Set的主要实现类有:HashSet,TreeSet,LinkedHashSet,这几个类得一共同点都是相同的只能保存一份。
2. HashSet
HashSet能够较快的获取集合中的元素,它是通过hashCode和equals方法来判断两个对象是否相等,如果hashCode值一样则会进一步调用equals方法来判断是否相等,如果为true则表示项目,如果为false则表示不同。
简单示例代码如下:
Student类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private String studentId;private String phone;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", studentId='" + studentId + '\'' +", phone='" + phone + '\'' +'}';}
}
Main测试方法如下:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class MainTest {public static void main(String[] args) {List<Student> list = new ArrayList<>();list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1234"));list.add(new Student("李四", "1234","2222"));list.add(new Student("李四", "1234","3333"));list.add(new Student("王五", "4567","2222"));list.add(new Student("老六", "8910","2222"));Set<Student> set = new HashSet<>();list.forEach(item->{if (!set.add(item)){System.out.println("该学生重复:" + item);}});System.out.println(set.size() + ": " + set);}}
输出结果如下:
HashSet的add方法会返回一个布尔类型的值,如果为true则表示插入成功,如果为false则插入失败(插入失败就是出现了重复的元素)。你会发现默认的是student类的三个属性name,student,phone相等才会判断相等。
进阶实例:
需求:只要姓名和学号相同的学生则认为是同一个学生
根据需求我们需要重写student类的hashcode和equals方法使其只需要判断姓名和学号即可。代码如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Objects;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private String studentId;private String phone;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", studentId='" + studentId + '\'' +", phone='" + phone + '\'' +'}';}@Overridepublic boolean equals(Object o) {System.out.println("我是equals方法");if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;//在这里默认会使用name,studentId, phone三个属性,我们只需要改为name和studentId属性即可
// return Objects.equals(name, student.name) && Objects.equals(studentId, student.studentId) && Objects.equals(phone, student.phone);//根据需求我们只需要该为只判断name和studentId即可return Objects.equals(name, student.name) && Objects.equals(studentId, student.studentId);}@Overridepublic int hashCode() {System.out.println("我是hashCode方法");//Objects.hash方法的参数是一个可变参数可以根据自己需求来变动//默认是使用类的所有属性的hashcode值来判断hashcode是否相同
// return Objects.hash(name, studentId, phone);//根据需求我们只需要给成name和studentId即可return Objects.hash(name, studentId);}
}
Main测试方法没变化:
import com.example.testdemo.entity.Student;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class MainTest {public static void main(String[] args) {List<Student> list = new ArrayList<>();list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1234"));list.add(new Student("李四", "1234","2222"));list.add(new Student("李四", "1234","3333"));list.add(new Student("王五", "4567","2222"));list.add(new Student("老六", "8910","2222"));Set<Student> set = new HashSet<>();list.forEach(item->{if (!set.add(item)){System.out.println("该学生重复:" + item);}});System.out.println(set.size() + ": " + set);}}
输出结果如下:
以上这种方法也是用的最多的。
3. TreeSet
TreeSet也不能插入重复元素并且能够进行排序(通过自然排序和定制排序)
3.1定制排序(比较器排序)
代码实例:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private String studentId;private String phone;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", studentId='" + studentId + '\'' +", phone='" + phone + '\'' +'}';}
}
import java.util.*;public class MainTest {public static void main(String[] args) {List<Student> list = new ArrayList<>();list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1234"));list.add(new Student("李四", "1234","2222"));list.add(new Student("李四", "1234","3333"));list.add(new Student("王五", "4567","2222"));list.add(new Student("老六", "8910","2222"));TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getName().compareTo(o2.getName()) + o1.getStudentId().compareTo(o2.getStudentId());}});list.forEach(item->{if (!set.add(item)){System.out.println("该学生重复:" + item);}});System.out.println(set.size() + ": " + set);}
}
其中compare方法的返回值如果是0则表示两者相等,如果是小于0则表示第一个对象o1小于第二个对象o2,如果大于0则表示o1大于o2(compare方法既有排序的作用也有去重的作用)
3.2自然排序:
实现comparable接口的compare方法
代码如下:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Comparable<Student> {private String name;private String studentId;private String phone;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", studentId='" + studentId + '\'' +", phone='" + phone + '\'' +'}';}@Overridepublic int compareTo(Student o) {return this.getName().compareTo(o.getName()) + this.getStudentId().compareTo(o.getStudentId());}
}
import com.example.testdemo.entity.Student;import java.util.*;public class MainTest {public static void main(String[] args) {List<Student> list = new ArrayList<>();list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1111"));list.add(new Student("张三", "1234","1234"));list.add(new Student("李四", "1234","2222"));list.add(new Student("李四", "1234","3333"));list.add(new Student("王五", "4567","2222"));list.add(new Student("老六", "8910","2222"));TreeSet<Student> set = new TreeSet<>();list.forEach(item->{if (!set.add(item)){System.out.println("该学生重复:" + item);}});System.out.println(set.size() + ": " + set);}
}
看自己喜欢用哪一个即可。
4. LinkedHashSet
LinkedHashSet是HashSet和LinkedHashMap的结合体。它既有HashSet的快速查找和不允许重复元素的特性,又有LinkedHashMap的有序性和迭代器的快速遍历特性。因此,在需要保持元素顺序的情况下,我们可以使用LinkedHashSet。
心中若有光芒,脚下自有道路,勇往直前,无畏前行!!!