java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java的WeakHashMap、TreeMap与Set

Java中的WeakHashMap、LinkedHashMap、TreeMap与Set详解

作者:超大充电宝

这篇文章主要介绍了Java中的WeakHashMap、LinkedHashMap、TreeMap与Set详解,在JVM中,一个对象如果不再被使用就会被当做垃圾给回收掉,判断一个对象是否是垃圾,我们的WeakHashMap就是基于弱引用,需要的朋友可以参考下

WeakHashMap

Java中的四种引用

在JVM中,一个对象如果不再被使用就会被当做垃圾给回收掉,判断一个对象是否是垃圾,通常有两种方法:引用计数法和可达性分析法。不管是哪一种方法判断一个对象是否是垃圾的条件总是一个对象的引用是都没有了。

JDK1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用、软引用、弱引用、虚引用4 种。而我们的WeakHashMap就是基于弱引用。

强引用

如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出OutOfMemoryError错误,使程序异常终止。比如String str = new String("hello");这时候str就是一个强引用。

软引用

内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。

弱引用

如果一个对象具有弱引用,在垃圾回收时候,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。

虚引用

如果一个对象具有虚引用,就相当于没有引用,在任何时候都有可能被回收。使用虚引用的目的就是为了得知对象被GC的时机,所以可以利用虚引用来进行销毁前的一些操作,比如说资源释放等。

LinkedHashMap

LinkedHashMap它虽然增加了时间和空间上的开销,但是通过维护一个运行于所有条目的双向链表,LinkedHashMap保证了元素迭代的顺序。该迭代顺序可以是插入顺序或者是访问顺序。

LinkedHashMap存储结构

/**
 * The head (eldest) of the doubly linked list.
 */
transient LinkedHashMap.Entry<K,V> head;
/**
 * The tail (youngest) of the doubly linked list.
 */
transient LinkedHashMap.Entry<K,V> tail;
/**
 * The iteration ordering method for this linked hash map: <tt>true</tt>
 * for access-order, <tt>false</tt> for insertion-order.
 *
 * @serial
 */
final boolean accessOrder;
/**
 * HashMap.Node subclass for normal LinkedHashMap entries.
 */
static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

LinkedHashMap的结点结构在继承于HashMap的基础上,增加了 before 和 after 属性来确保插入顺序。并且还维护了头结点 head 和尾结点 tail 。在插入数据时,不但需要通过哈希算法进行存储,还需要通过 before 和 after 模拟双向链表存储结构,进行插入顺序的维护。

LinkedHashMap所继承于HashMap结点中的 next 属性是用于维护HashMap中table数组中存储的链表。而其独有的 before 和 after 是模拟双向链表进行结点插入顺序的维护

TreeMap

在前面我们通过HashMap中插入顺序无序引出了LinkedHashMap的使用,但是我们又可以发现,这两种存储方式在迭代时均不是按照数据的大小顺序进行遍历的,而当我们需要将数据按照大小顺序迭代时,就需要此时的TreeMap集合了。

TreeMap的存储结构

// Red-black mechanics
private static final boolean RED   = false;
private static final boolean BLACK = true;
/**
 * Node in the Tree.  Doubles as a means to pass key-value pairs back to
 * user (see Map.Entry).
 */
static final class Entry<K,V> implements Map.Entry<K,V> {
    //key,val是存储的原始数据
    K key;
    V value;
    //定义了结点的左孩子
    Entry<K,V> left = null;
    //定义了结点的右孩子
    Entry<K,V> right = null;
    //通过该节点可以反过来往上找到自己的父亲
    Entry<K,V> parent;
    //默认情况下为黑色节点,可调整
    boolean color = BLACK;
    /**
     * Make a new cell with given key, value, and parent, and with
     * {@code null} child links, and BLACK color.
     */
    Entry(K key, V value, Entry<K,V> parent) {
        this.key = key;
        this.value = value;
        this.parent = parent;
    }
}

黑树规则特点:

1、节点分为红色或者黑色;

2、根节点必为黑色;

3、叶子节点都为黑色,且为null;

4、连接红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点);

5、从任意节点出发,到其每个叶子节点的路径中包含相同数量的黑色节点;

6、新加入到红黑树的节点为红色节点;

红黑树自平衡基本操作:

1、变色:在不违反上述红黑树规则特点情况下,将红黑树某个node节点颜色由红变黑,或者由黑变红;

2、左旋:逆时针旋转两个节点,让一个节点被其右子节点取代,而该节点成为右子节点的左子节点;

3、右旋:顺时针旋转两个节点,让一个节点被其左子节点取代,而该节点成为左子节点的右子节点;

Set

Set集合类似于一个罐子,程序可以依次把多个对象“丢进”Set集合,而Set集合通常不能记住元素的添加顺序。实际上Set就是Collection只是行为略有不同(Set不允许包含重复元素)。

Set集合不允许包含相同的元素,如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。

Set集合的特征

HashSet

HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。底层数据结构是哈希表。

HashSet特点

HashSet具有以下特点:

HashSet的存储结构

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals方法比较true,但它们的hashCode方法返回的值不相等,HashSet将会把它们存储在不同位置,依然可以添加成功。

也就是说。HashSet集合判断两个元素的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等。

即:靠元素重写hashCode方法和equals方法来判断两个元素是否相等,如果相等则覆盖原来的元素,以此来确保元素的唯一性。

TreeSet

TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。

存储结构 TreeSet内部实现的是红黑树,默认整形排序为从小到大。

在这里插入图片描述

常用方法

与HashSet集合相比,TreeSet还提供了几个额外方法:

排序方式

TreeSet支持两种排序方法:自然排序和定制排序,在默认情况下,采用的是自然排序。

EnumSet

EnumSet类的特点:

EnumSet类没有暴露任何构造器来创建该类的实例,EnumSet类提供了以下类方法来创建EnumSet对象。

到此这篇关于Java中的WeakHashMap、LinkedHashMap、TreeMap与Set详解的文章就介绍到这了,更多相关Java的WeakHashMap、TreeMap与Set内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文