HashSet , TreeSet , LinkedHashSet 对比

本文详细比较了Java中HashSet、TreeSet和LinkedHashSet三种集合类的特点及适用场景,并通过具体实例展示了它们的不同之处,包括元素的存储顺序、性能差异等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Set 是一个没有重复元素的集合。何时使用是一个重要的问题。简而言之,如果您需要一个快速集合,您应该使用HashSet;如果您需要一个排序集合,那么应该使用TreeSet;如果您需要一个可以存储插入顺序的集合,那么应该使用LinkedHashSet。

1. Set Interface

Set是继承Collection 接口的。
这里写图片描述

2. HashSet ,TreeSet ,LinkedHashSet的区别

HashSet 是由hash table实现的,元素是无序的,添加、删除和包含方法具有常量时间复杂度O(1)。
TreeSet 是使用树形结构(算法书中的红黑树)实现的。集合中的元素是有序的,但是add、remove和包含方法的时间复杂度是O(log(n)),它提供了几个有序集合处理方法,比如first(), last(), headSet(), tailSet()等等。
LinkedHashSet 位于 HashSet和TreeSet之间。是由hash table和linked list实现的,所以是以插入顺序保存的。基本方法的时间复杂度是O(1)。

3. TreeSet 的例子

TreeSet<Integer> tree = new TreeSet<Integer>();
tree.add(12);
tree.add(63);
tree.add(34);
tree.add(45);

Iterator<Integer> iterator = tree.iterator();
System.out.print("Tree set data: ");
while (iterator.hasNext()) {
    System.out.print(iterator.next() + " ");
}

输出结果:

Tree set data: 12 34 45 63

Dog类:

class Dog {
    int size;

    public Dog(int s) {
        size = s;
    }

    public String toString() {
        return size + "";
    }

遍历Dog:

import java.util.Iterator;
import java.util.TreeSet;

public class TestTreeSet {
    public static void main(String[] args) {
        TreeSet<Dog> dset = new TreeSet<Dog>();
        dset.add(new Dog(2));
        dset.add(new Dog(1));
        dset.add(new Dog(3));

        Iterator<Dog> iterator = dset.iterator();

        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
    }
}

结果报错了:

Exception in thread “main” java.lang.ClassCastException: collection.Dog cannot be cast to java.lang.Comparable
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at collection.TestTreeSet.main(TestTreeSet.java:22)

因为TreeSet是有序的,Dog类需要实现java.lang.Comparable’s compareTo() 方法。

class Dog implements Comparable<Dog>{
    int size;

    public Dog(int s) {
        size = s;
    }

    public String toString() {
        return size + "";
    }

    @Override
    public int compareTo(Dog o) {
            return size - o.size;
    }
}

结果为:

1 2 3

4. HashSet 的例子

HashSet<Dog> dset = new HashSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
dset.add(new Dog(5));
dset.add(new Dog(4));
Iterator<Dog> iterator = dset.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + " ");
}

结果:

5 3 2 1 4

注意输出顺序是乱的。

5. LinkedHashSet 的例子

LinkedHashSet<Dog> dset = new LinkedHashSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
dset.add(new Dog(5));
dset.add(new Dog(4));
Iterator<Dog> iterator = dset.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + " ");
}

结果:

2 1 3 5 4

性能测试

add() 方法的性能:

public static void main(String[] args) {
Random r = new Random();
HashSet<Dog> hashSet = new HashSet<Dog>();
TreeSet<Dog> treeSet = new TreeSet<Dog>();
LinkedHashSet<Dog> linkedSet = new LinkedHashSet<Dog>();
// start time
long startTime = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int x = r.nextInt(1000 - 10) + 10;
hashSet.add(new Dog(x));
}
// end time
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println("HashSet: " + duration);
// start time
startTime = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int x = r.nextInt(1000 - 10) + 10;
treeSet.add(new Dog(x));
}
// end time
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("TreeSet: " + duration);
// start time
startTime = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int x = r.nextInt(1000 - 10) + 10;
linkedSet.add(new Dog(x));
}
// end time
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("LinkedHashSet: " + duration);
}

结果,HashSet是最快的跟LinkedHashSet是差不多,但是TreeSet是最慢的:

HashSet: 2244768
TreeSet: 3549314
LinkedHashSet: 2263320

*测试不是精确的,但是可以反映出TreeSet要慢得多的基本思想,因为它是有序的。

这里写图片描述

转自:https://www.programcreek.com/2013/03/hashset-vs-treeset-vs-linkedhashset/

但是本人亲自实验却与测试结果不同!

package com.moha.demo.util;


import java.util.*;

public class SetMain {
    public static void main(String[] args) {


        Random r = new Random();

        HashSet<Dog> hashSet = new HashSet<Dog>();
        TreeSet<Dog> treeSet = new TreeSet<Dog>();
        LinkedHashSet<Dog> linkedSet = new LinkedHashSet<Dog>();



        // start time
        long startTime = System.nanoTime();

        for (int i = 0; i < 1000; i++) {
            int x = r.nextInt(1000 - 10) + 10;
            hashSet.add(new Dog(x));
        }
        // end time
        long endTime = System.nanoTime();
        long duration = endTime - startTime;
        System.out.println("HashSet: " + duration);

        // start time
        startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            int x = r.nextInt(1000 - 10) + 10;
            treeSet.add(new Dog(x));
        }
        // end time
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("TreeSet: " + duration);

        // start time
        startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            int x = r.nextInt(1000 - 10) + 10;
            linkedSet.add(new Dog(x));
        }
        // end time
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("LinkedHashSet: " + duration);

        // start time
        startTime = System.nanoTime();
        Iterator<Dog> iterator = hashSet.iterator();
        while (iterator.hasNext()) {
            iterator.next();
        }
        // end time
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("HashSetget: " + duration);


        startTime = System.nanoTime();
        iterator = treeSet.iterator();
        while (iterator.hasNext()) {
            iterator.next();
        }
        // end time
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("TreeSetget: " + duration);


        startTime = System.nanoTime();
        iterator = linkedSet.iterator();
        while (iterator.hasNext()) {
            iterator.next();
        }
        // end time
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("LinkedHashSetget: " + duration);


    }
}

结果:

HashSet: 1059056
TreeSet: 736775
LinkedHashSet: 543965
HashSetget: 325696
TreeSetget: 388414
LinkedHashSetget: 169213

数据有在波动,但每次结果却基本都是HashSet的插入时间消耗最久了,LinkedHashSet的查询时间最快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值