【JAVA基础】HashSet、LinkedHashSet、TreeSet使用区别

本文详细介绍了 Java 中三种 Set 实现:HashSet、LinkedHashSet 和 TreeSet 的特点及使用场景。通过实例展示了不同集合在存储元素时的行为差异,包括无序、插入顺序保持和排序等功能。

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

 

 

【JAVA基础】HashSet、LinkedHashSet、TreeSet使用区别

 

HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放;

LinkedHashSet:以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代;  

TreeSet:提供一个使用树结构存储Set接口的实现,对象以升序顺序存储,访问和遍历的时间很快。

用例代码:

复制代码
package com.test;  

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;

/**
* @description 几个set的比较
* HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放;
* LinkedHashSet:以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代;
* TreeSet:提供一个使用树结构存储Set接口的实现,对象以升序顺序存储,访问和遍历的时间很快。
*
@author Zhou-Jingxian
*
*/
public class SetDemo {

public static void main(String[] args) {

HashSet<String> hs = new HashSet<String>();
hs.add("B");
hs.add("A");
hs.add("D");
hs.add("E");
hs.add("C");
hs.add("F");
System.out.println("HashSet 顺序:\n"+hs);

LinkedHashSet<String> lhs = new LinkedHashSet<String>();
lhs.add("B");
lhs.add("A");
lhs.add("D");
lhs.add("E");
lhs.add("C");
lhs.add("F");
System.out.println("LinkedHashSet 顺序:\n"+lhs);

TreeSet<String> ts = new TreeSet<String>();
ts.add("B");
ts.add("A");
ts.add("D");
ts.add("E");
ts.add("C");
ts.add("F");
System.out.println("TreeSet 顺序:\n"+ts);
}
}
复制代码


输出效果:

HashSet 顺序:
[D, E, F, A, B, C]
LinkedHashSet 顺序:
[B, A, D, E, C, F]
TreeSet 顺序:
[A, B, C, D, E, F]

 

 

HashSet的输出结果分析:

 

hashset的实现,依据的是hashmap,

举个hashset源码的小例子:

 

public boolean add(E e) {
	return map.put(e, PRESENT)==null;
    }

 所以我们分析hashmap的源码:

 

 

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

 最为重要的就是:hash的生成算法和indexfor确定的table[i]的下标:

 

 

static int hash(int h) {
        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    /**
     * Returns index for hash code h.
     */
    static int indexFor(int h, int length) {
        return h & (length-1);
    }

 这样,就解释了为什么hashset的输出如此不同,它是根据hash值的生成策略来存储在散列表中的。

 

 

hashmap的源码,是根据transient Entry[] table;以及生成entry内部类,来实现散列表的。

当然,我们在做应用时,也可以使用linkedList[],来实现散列表。

代码如下:

 

public class HashTest {
	static final int tablesize = 13;
	LinkedList<Integer>[] listTable;
	String[] s = new String[12];
	
	public void load(Iterator<Integer> it) {
		listTable = (LinkedList<Integer>[])new LinkedList[tablesize];
		
		while(it.hasNext()) {
			Integer temp = it.next();
			int n = hash(temp);
			if(listTable[n] == null) {
				listTable[n] = new LinkedList<Integer>();
			}
			listTable[n].add(temp);
		}
	}

	private int hash(Integer temp) {
//		int v = temp.hashCode(); //比较对象(字符串)时,取得hash值
		int v = temp;		
		return v % tablesize;
	}
	
	private boolean search(Integer v) {
		int h = hash(v);
		LinkedList<Integer> ll = listTable[h];
		if(ll == null) return false;
		return ll.contains(v);
	}
	
	public static void main(String[] args) {
		HashTest ht = new HashTest();
		List<Integer> li = new ArrayList<Integer>();
		for(int i=0;i<10000;i++) {
			li.add(i);
		}
		ht.load(li.iterator());
		int a = 10000;
		if(ht.search(a)) {
			System.out.println("yes");
		} else {
			System.out.println("no");
		}
//		HashSet<String> hs = new HashSet<String>();
//		hs.add("D");
//		hs.add("B");
//		hs.add("E");
//		hs.add("A");
//		hs.add("F");
//		hs.add("C");
//		System.out.println(hs);
//		
//		System.out.println(17 & 16);
	}
	
}

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值