hashSet linkedHashSet treeSet 一点区别

上代码先:

	  Set<String> hashSet=new HashSet<String>();
	  hashSet.add("thireBottom");
	  hashSet.add("thirdTop");
	  System.out.println(hashSet);
	  
	  Set<String> linkedSet=new LinkedHashSet<String>();
	  linkedSet.add("thireBottom");
	  linkedSet.add("thirdTop");
	  System.out.println(linkedSet);
	  
	  Set<String> treeSet=new TreeSet<String>();
	  treeSet.add("thirdTop");
	  treeSet.add("thireBottom");
	  System.out.println(treeSet);

结果如下:

[thirdTop, thirdBottom]
[thirdBottom, thirdTop]
[thirdBottom, thirdTop]


工作了许久有时候也没注意到这些细节上的东西,今天刚好碰到一个需求就是要求Set集合按照一定的顺序输出,翻了下hashSet的源码,简单mark下.

对于hashSet这个集合,本质是基于hashMap的ketSet()实现的.  keySet()类似一个数组集合, 当往里面add数据的时候, 会先计算该数据的hashCode值, 根据该值存入到数组集合中.例子中: thirdTop 的hashCode值对应的数组下标排在thirdBottom前面,所以输出 thirdTop, thirdBottom

在来看一个列子:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class Test {
	
	  public static void main(String args[]){
		  testB();
	  }
	  
	  public static void testB(){
		  
		  Set<HashObject> set=new HashSet<HashObject>();
		  
		  HashObject object1=new HashObject();
		  object1.setCode(10);
		  System.out.println(object1);
		  
		  HashObject object2=new HashObject();
		  object2.setCode(54);
		  System.out.println(object2);
		  
		  HashObject object3=new HashObject();
		  object3.setCode(32);
		  System.out.println(object3);
		  
		  set.add(object1);
		  set.add(object2);
		  set.add(object3);
		  
		  System.out.println();
		  System.out.println("object1在数组中的下标:"+String.valueOf(15&41));  // 长度&hashCode
		  System.out.println("object2在数组中的下标:"+String.valueOf(15&85));  // 长度&hashCode
		  System.out.println("object3在数组中的下标:"+String.valueOf(15&63));  // 长度&hashCode
		  System.out.println();
		  
		  System.out.println(set);
		  
	  }
	  
	  static class HashObject{
		  
		  private Integer code;

		 @Override
		 public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((code == null) ? 0 : code.hashCode());
			return result;
		}

		public Integer getCode() {
			return code;
		}

		public void setCode(Integer code) {
			this.code = code;
		}
	
	  }
}

hashObject 对象的hashCode值可以通过重写 该类的hashCode()方法实现, 但是需要区分的是hashCode不等于hashOject所存储的数组列表的下标,即不是按照hashCode大小顺序存入数组列表, hashCode到数组下标转换方法如下(在hashMap源码中定义):

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

当前数组列表的长度-1 &  hashCode 即得到数组下标,输出顺序,结果如下:

Test$HashObject@29
Test$HashObject@55
Test$HashObject@3f

object1在数组中的下标:9
object2在数组中的下标:5
object3在数组中的下标:15

[Test$HashObject@55, Test$HashObject@29, Test$HashObject@3f]


结论: hashSet 中的数据排序和你插入顺序无关, 也没有指定的排序方法供你选择, 结果可以简单理解为不可预知的(其实还是根据hashCode来的)

linkedHashSet 数据插入不是基于数组,而是以链式存储,通过前后指针相互关联.所以数据插入顺序决定了输出顺序

treeSet <E> 相比上面则提供了,排序的方法。 插入的对象必须实现 comparable接口以提供排序方法, 如果是字符串默认就是按照字母顺序排序。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值