简易记录 HashSet 和TreeSet区别

HashSet 和TreeSet

HashSet 特点:

  • 不能保证元素的顺序,元素的顺序可能会发生变化
  • 不能同步的,线程不安全的
  • 集合元素可以是Null,但是只能有一个Null

HashSet 简易原理:
HashSet是底层是由HashMap组成的当向HashSet插入一个元素的时候,首先调用该对象的HashCode()方法获取HashCode,在根据HashCode判断该对象应该储存在那个位置
HashSet中无法储存相同的对象,如果HashCode相同在调用equals方法判断是否属于同一个对象,所以存入HashSet的对象都必须实现HashCode()和equals方法

HashSet 部分源码:

  • 核心属性
 //数据都存放在这个Map当中
 private transient HashMap<E,Object> map;
 //Map 中所有的Key都是一个Object
 private static final Object PRESENT = new Object();
  • 4个构造函数
   public HashSet() {
   		//创建一个Map Map默认长度为16
   		//由于HashSet底层是HashMap 所以扩容机制如同HashMap
   		//当元素超过 当前容量*负载因子(0.75f)的时候就会进行扩容
   		// 每一次扩容是当前容量的1倍 
        map = new HashMap<>();
    }

	public HashSet(Collection<? extends E> c) {
		//比较让如的集合和默认长度16哪一个大
		//如果放入的长度小于16则使用默认长度,并且吧所有对象addAll
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }
    
	public HashSet(int initialCapacity, float loadFactor) {
		//可自己填写默认容量已经负载因子
        map = new HashMap<>(initialCapacity, loadFactor);
    }
    
	public HashSet(int initialCapacity) {
		//可填写默认容量 负载因子使用默认的0.75f
        map = new HashMap<>(initialCapacity);
    }
    
    public int size() {
    	//大部分操作直接调用map
        return map.size();
    }

	public boolean contains(Object o) {
        return map.containsKey(o);
    }
    
	public boolean add(E e) {
		// add操作的时候 首先调用该对象的HashCode()方法获取HashCode,在根据HashCode			判断该对象应该储存在那个位置HashSet中无法储存相同的对象,如果HashCode相同在调用equals方法判断是否属于同一个对象
		// 计算出来的对象 当做Map的Key,Value都是统一的PRESENT (new Object())
        return map.put(e, PRESENT)==null;
    }

TreeSet 特点:

  1. 能够保证元素的顺序,TreeSet 支持二中排序方式,自然排序和定制排序,默认使用自然排序,定制排序需要在构造函数当中传入一个比较器
  2. 不允许存放Null,如果存放Null则直接NullPointerException
  3. 数据不同步的,线程不安全的

TreeSet简易理解:
TreeSet 是基于TreeMap实现的,TreeMap 是一个具有自然排序依据定制排序的map,能够保证数据的顺序排序,TreeSet 使用二叉平衡树来储存数据,由于要顺序排序所以性能相对来说比较差

TreeSet 部分源码:

 // 数据都储存在这NavigableMap当中 TreeMap 实现了NavigableMap 
 private transient NavigableMap<E,Object> m;
 // 和HashSet 一样 TreeSet中的Map value 都储存的是一个Object
 private static final Object PRESENT = new Object();


   //无参构造函数 直接创建一个New TreeMap();
   // TreeMap 底层是由红黑树维护的所以不存在容量 或者扩容机制
  public TreeSet() {
      this(new TreeMap<E,Object>());
  }
  // 放入一个定制比较器进行构造
  public TreeSet(Comparator<? super K> comparator) {
      this.comparator = comparator;
  }
  // 放入一个集合 然后调用addAll
  public TreeSet(Collection<? extends E> c) {
      this();
      addAll(c);
  }
  public  boolean addAll(Collection<? extends E> c) {
        // 调用全局的 map 判断size 是否有数据 
        // 并且 传入类型是否是SortedSet  或者TreeMap 如果不是
        // 调用父类AbstractCollection 的addAll
        if (m.size()==0 && c.size() > 0 &&
            c instanceof SortedSet &&
            m instanceof TreeMap) {
            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
            Comparator<?> cc = set.comparator();
            Comparator<? super E> mc = map.comparator();
            if (cc==mc || (cc != null && cc.equals(mc))) {
                map.addAllForTreeSet(set, PRESENT);
                return true;
            }
        }
        //AbstractCollection 中的addAll 直接迭代所有的kev 并切入到set当中
        return super.addAll(c);
    }
	//add 操作 直接 将 输入的值当做Map的key 
	//PRESENT (new Object())  作为 value存入Map
   public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
    // 大部分操作 直接调用TreeMap中的方法 (contains size isEmpty)
	........
 

HashSet 和TreeSet 大部分特点相同, Treeset可以保持元素的顺序,由于需要保持元素顺序,所以性能略差,HashSet的性能要好得多,是因为HashSet的底层是有HashMap储存的访问速度非常快,如果不需要保持元素属性并且不要求重复可以使用HashSet,如果需要元素顺序则使用TreeSet

1,treeSet去重原理:compareTo

可以实现排序及去重:如果compareTo返回0,说明是重复的,返回的是自己的某个属性和另一个对象的某个属性的差值,如果是负数,则往前面排,如果是正数,往后面排;

应用:类实现compareable接口,覆写其compareto方法,根据自己的需要改变其排序及去重规则,比如person类,根据其年龄进行去重和排序

2,hashSet去重原理:1,hashCode 2,equals是否相同
两个方法可以快速生成,hashCode是几个属性的hashCode共同计算的结果
(基本数据类型的实现类生成的hashCode是其拆箱后的值的比较,跟引用数据类型的规则不同,如Integer类)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值