set集合分类总结(hashSet、treeSet、linkedHashSet)

时间:2021-09-02 15:26:00

首先我们要知道set集合作为Collection家族的一员,他的作用就是存储数据,而且是不可重复的无序数据。

那set集合分为hashSet、treeSet和linkedHashSet,我们怎么来区分什么情况下使用呢...

1、如果我们需要将元素排序, 那么使用TreeSet

2、如果我们不需要排序, 使用HashSet, HashSet比TreeSet效率高

3、如果我们需要保留存储顺序, 又要过滤重复元素, 那么使用LinkedHashSet

hashSet:

哈希表边存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同)是按照哈希值来存的所以取数据也是按照哈希值取得。

HashSet不存入重复元素的规则.使用hashcode和equals

由于Set集合是不能存入重复元素的集合。那么HashSet也是具备这一特性的。HashSet如何检查重复?

HashSet会通过元素的hashcode()和equals方法进行判断元素师否重复。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
// Set 集合存和取的顺序不一致。
Set hs = new HashSet();
hs.add("乐视网");
hs.add("腾讯视频");
hs.add("优酷");
hs.add("爱奇艺");
// 返回此 set 中的元素的数量
System.out.println(hs.size()); // 4
// 如果此 set 尚未包含指定元素,则返回 true
boolean add = hs.add("乐视网"); // false
System.out.println(add);
// 返回此 set 中的元素的数量
System.out.println(hs.size());// 4
Iterator it = hs.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

TreeSet:

红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

set集合分类总结(hashSet、treeSet、linkedHashSet)

红黑树原理和算法介绍:http://www.cnblogs.com/skywang12345/p/3245399.html

红黑树算法的规则: 左小右大。

既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。

1:让存入的元素自定义比较规则。

2:给TreeSet指定排序规则。

方式一:元素自身具备比较性

元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

方式二:容器具备比较性

当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。

注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)

通过return 0来判断唯一性。

TreeSet集合排序的两种方式:

一,让元素自身具备比较性。

也就是元素需要实现Comparable接口,覆盖compareTo 方法。

这种方式也作为元素的自然排序,也可称为默认排序。

年龄按照搜要条件,年龄相同再比姓名。

import java.util.TreeSet;
public class Demo4 {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Person("aa", 20, "男"));
ts.add(new Person("bb", 18, "女"));
ts.add(new Person("cc", 17, "男"));
ts.add(new Person("dd", 17, "女"));
ts.add(new Person("dd", 15, "女"));
ts.add(new Person("dd", 15, "女"));
System.out.println(ts);
System.out.println(ts.size()); // 5
}
}
class Person implements Comparable {
private String name;
private int age;
private String gender;
public Person() {
}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public int hashCode() {
return name.hashCode() + age * 37;
}
public boolean equals(Object obj) {
System.err.println(this + "equals :" + obj);
if (!(obj instanceof Person)) {
return false;
}
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
}
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender
+ "]";
}
@Override
public int compareTo(Object obj) {
Person p = (Person) obj;
System.out.println(this+" compareTo:"+p);
if (this.age > p.age) {
return 1;
}
if (this.age < p.age) {
return -1;
}
return this.name.compareTo(p.name);
}
}

二、让容器自身具备比较性,自定义比较器。

需求:当元素自身不具备比较性,或者元素自身具备的比较性不是所需的。

那么这时只能让容器自身具备。

定义一个类实现Comparator 接口,覆盖compare方法。

并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。

当Comparable比较方式,及Comparator比较方式同时存在,以Comparator

比较方式为主。

import java.util.Comparator;
import java.util.TreeSet;
public class Demo5 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new MyComparator());
ts.add(new Book("think in java", 100));
ts.add(new Book("java 核心技术", 75));
ts.add(new Book("现代操作系统", 50));
ts.add(new Book("java就业教程", 35));
ts.add(new Book("think in java", 100));
ts.add(new Book("ccc in java", 100));
System.out.println(ts);
}
}
class MyComparator implements Comparator {
public int compare(Object o1, Object o2) {
Book b1 = (Book) o1;
Book b2 = (Book) o2;
System.out.println(b1+" comparator "+b2);
if (b1.getPrice() > b2.getPrice()) {
return 1;
}
if (b1.getPrice() < b2.getPrice()) {
return -1;
}
return b1.getName().compareTo(b2.getName());
}
}
class Book {
private String name;
private double price;
public Book() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Book(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Book [name=" + name + ", price=" + price + "]";
}
}

LinkedHashSet:

既可以排序又可以去重;


总结:

看到array,就要想到数组角标。

看到link,就要想到first,last。

看到hash,就要想到hashCode,equals.

看到tree,就要想到两个接口:Comparable,Comparator。