集合

图片 6

本文由码农网 –
小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

集合类之间的继承关系:

图片 1

java集合类,java集合

ArrayList是Java中最常用的集合类型之一。它允许灵活添加多个null元素,重复的元素,并保持元素的插入顺序。在编码时我们经常会遇到那种必须从已建成的ArrayList中删除重复元素的要求。这篇文章将给出两种从ArrayList中删除重复元素的方法。

Set集合

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

Java集合类

图片 2

一、HashSet类

HashSet是Set接口的典型实现,实现了Set接口中的所有方法,并没有添加额外的方法,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素。因此具有很好的存取和查找性能。

HashSet特点:

1.不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。

2.HashSet不是同步的,如果多个线程同时访问一个HashSet,则必须通过代码来保证其同步。

3.集合元素值可以是null。

除此之外,HashSet判断两个元素是否相等的标准也是其一大特点。HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

LinkedHashSet类

LinkedHashSet是HashSet对的子类,也是根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,使得元素是以插入的顺序来保存的。当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。但是由于要维护元素的插入顺序,在性能上略低与HashSet,但在迭代访问Set里的全部元素时有很好的性能。

注意:LinkedHashSet依然不允许元素重复,判断重复标准与HashSet一致。

补充:HashSet的实质是一个HashMap。HashSet的所有集合元素,构成了HashMap的key,其value为一个静态Object对象。因此HashSet的所有性质,HashMap的key所构成的集合都具备。

1.简介:

java集合类包含在java.util包下

集合类存放的是对象的引用,而非对象本身。

集合类型主要分为Set(集),List(列表),Map(映射)。

方法1:使用HashSet删除ArrayList中重复的元素

在该方法中,我们使用HashSet来删除重复的元素。如你所知,HashSet不允许有重复的元素。我们使用HashSet的这个属性来删除已建成的ArrayList中的重复元素。但是,这种方法有一个缺点。那就是,它会删除ArrayList中元素的插入顺序。这意味着,删除重复的元素后,元素的插入顺序就不对了。先来看下面这个例子。

import java.util.ArrayList;
import java.util.HashSet;

public class MainClass
{
    public static void main(String[] args)
    {
        //Constructing An ArrayList

        ArrayList<String> listWithDuplicateElements = new ArrayList<String>();

        listWithDuplicateElements.add("JAVA");

        listWithDuplicateElements.add("J2EE");

        listWithDuplicateElements.add("JSP");

        listWithDuplicateElements.add("SERVLETS");

        listWithDuplicateElements.add("JAVA");

        listWithDuplicateElements.add("STRUTS");

        listWithDuplicateElements.add("JSP");

        //Printing listWithDuplicateElements

        System.out.print("ArrayList With Duplicate Elements :");

        System.out.println(listWithDuplicateElements);

        //Constructing HashSet using listWithDuplicateElements

        HashSet<String> set = new HashSet<String>(listWithDuplicateElements);

        //Constructing listWithoutDuplicateElements using set

        ArrayList<String> listWithoutDuplicateElements = new ArrayList<String>(set);

        //Printing listWithoutDuplicateElements

        System.out.print("ArrayList After Removing Duplicate Elements :");

        System.out.println(listWithoutDuplicateElements);
    }
}

输出:

ArrayList With Duplicate Elements :[JAVA, J2EE, JSP, SERVLETS, JAVA, STRUTS, JSP]
ArrayList After Removing Duplicate Elements :[JAVA, SERVLETS, JSP, J2EE, STRUTS]

注意输出结果。你会发现,在删除重复元素之后,元素重新洗牌。不再按照插入顺序排列。如果你想在删除重复的元素之后依然保持元素的插入顺序,那么不建议使用此方法。还有另一种方法,可以保证在删除重复的元素之后也不改变元素的插入顺序。那就是使用LinkedHashSet。

二、TreeSet类

TreeSet简介

TreeSet中所谓的有序,不同于之前所讲的插入顺序,而是通过集合中元素属性进行排序方式来实现的。

比较器Comparator:

图片 3

1.1 java集合类图

图片 4

方法2:使用LinkedHashSet删除ArrayList中重复的元素

在该方法中,我们使用LinkedHashSet删除ArrayList中重复的元素。正如你知道的,LinkedHashSet不允许重复元素,同时保持元素的插入顺序。LinkedHashSet的这两个属性可以确保在删除ArrayList中的重复元素之后,依然保持元素的插入顺序。参见下面的例子。

import java.util.ArrayList;
import java.util.LinkedHashSet;

public class MainClass
{
    public static void main(String[] args)
    {
        //Constructing An ArrayList

        ArrayList<String> listWithDuplicateElements = new ArrayList<String>();

        listWithDuplicateElements.add("JAVA");

        listWithDuplicateElements.add("J2EE");

        listWithDuplicateElements.add("JSP");

        listWithDuplicateElements.add("SERVLETS");

        listWithDuplicateElements.add("JAVA");

        listWithDuplicateElements.add("STRUTS");

        listWithDuplicateElements.add("JSP");

        //Printing listWithDuplicateElements

        System.out.print("ArrayList With Duplicate Elements :");

        System.out.println(listWithDuplicateElements);

        //Constructing LinkedHashSet using listWithDuplicateElements

        LinkedHashSet<String> set = new LinkedHashSet<String>(listWithDuplicateElements);

        //Constructing listWithoutDuplicateElements using set

        ArrayList<String> listWithoutDuplicateElements = new ArrayList<String>(set);

        //Printing listWithoutDuplicateElements

        System.out.print("ArrayList After Removing Duplicate Elements :");

        System.out.println(listWithoutDuplicateElements);
    }
}

输出:

ArrayList With Duplicate Elements :[JAVA, J2EE, JSP, SERVLETS, JAVA, STRUTS, JSP]
ArrayList After Removing Duplicate Elements :[JAVA, J2EE, JSP, SERVLETS, STRUTS]

注意输出。你可以发现在删除ArrayList中的重复元素后,依然保持了元素的插入顺序。

List集合

从上述类图,自己整理出主要内容是如下:

图片 5

一、ArrayList

ArrayList和Vector作为List类的两个典型实现,完全支持之前介绍的List接口的全部功能。

ArrayList和Vector类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态的、允许再分配的Object[]数组。ArrayList或Vector对象使用initalCapacity参数来设置该数组的长度,当向ArrayList或Vector中添加元素超过了该数组的长度时,它们的initalCapacity会自动增加。

ArrayList和Vector的区别:

1.ArrayList是线程不安全的,Vector是线程安全的。

2.Vector的性能比ArrayList差。

2.集合详解

二、LinkedList

LinkedList类是List接口的实现类——这意味着它是一个List集合,可以根据索引来随机访问集合中的元素。除此之外,LinkedList还实现了Deque接口,可以被当作成双端队列来使用,因此既可以被当成“栈”来使用,也可以当成队列来使用。

LinkedList的实现机制与ArrayList完全不同。ArrayList内部是以数组的形式来保存集合中的元素的,因此随机访问集合元素时有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能比较出色。

2.1 HashSet

HashSet是Set接口的一个子类

主要的特点是:

  • 里面不能存放重复元素,元素的插入顺序与输出顺序不一致

  • 采用散列的存储方法,所以没有顺序。

!ArrayList与LinkedList性能对比!

ArrayList
是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。ArrayList应使用随机访问(即,通过索引序号访问)遍历集合元素。

LinkedList
是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率高。LinkedList应使用采用逐个遍历的方式遍历集合元素。

(01) 对于需要快速插入,删除元素,应该使用LinkedList。

(02) 对于需要快速随机访问元素,应该使用ArrayList。

(03) 对于“单线程环境” 或者
“多线程环境,但List仅仅只会被单个线程操作”,此时应该使用非同步的类(如ArrayList)。对于“多线程环境,且List可能同时被多个线程操作”,此时,应该使用同步的类(如Vector)。

图片 6

代码实例:HashSetTest

package cn.swum;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class HashSetTest {

    public static void main(String[] args) {

        Set set = new HashSet();

        set.add("a");
        set.add("b");
        set.add("c");
        set.add("d");
        set.add("f");
        //插入重复元素,测试set是否可以存放重复元素
        set.add("a");
        set.add(null);
        //插入重复null,看结果是否可以存放两个null
        set.add(null);

        Iterator iter = set.iterator();

        System.out.println("输出的排列顺序为:");

        while (iter.hasNext()){

            System.out.println( iter.next());
        }

    }
}

输出结果:

图片 7

HashMap与Hashtable的区别

1.Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable的性能好一些;但如果有多个线程访问同一个Map对象时,是盗用Hashtable实现类会更好。

2.Hashtable不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发NullPointerException异常;但是HashMap可以使用null作为key或value。

小结:

HashSet存放的值无序切不能重复,可以存放null,但只能存放一个null值

HashSet
继承AbstractSet,有两个重要的方法,其中HashCode()和equals()方法,当对象被存储到HashSet当中时,会调用HashCode()方法,获取对象的存储位置。

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

TreeMap

TreeMap是SortedMap接口的实现类。TreeMap
是一个有序的key-value集合,它是通过红黑树实现的。

2.2 LinkedHashSet

  • LinkedHashSet是HashSet的一个子类

  • 只是HashSet底层用的HashMap,

    而LinkedHashSet底层用的LinkedHashMap

Map实现类的性能分析及适用场景

HashMap与Hashtable实现机制几乎一样,但是HashMap比Hashtable性能更好些。

LinkedHashMap比HashMap慢一点,因为它需要维护一个双向链表。

TreeMap比HashMap与Hashtable慢(尤其在插入、删除key-value时更慢),因为TreeMap底层采用红黑树来管理键值对。

适用场景:

一般的应用场景,尽可能多考虑使用HashMap,因为其为快速查询设计的。

如果需要特定的排序时,考虑使用TreeMap。

如果仅仅需要插入的顺序时,考虑使用LinkedHashMap。

LinkedHashSet代码实例:

package cn.swum;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetTest {

    public static void main(String[] args) {

        Set set = new LinkedHashSet();

        set.add("a");
        set.add("b");
        set.add("c");
        set.add("d");
        set.add("e");

        System.out.println("LinkedHashSet存储值得排序为:");

        for (Iterator iter = set.iterator();iter.hasNext();){
            System.out.println(iter.next());

        }

    }

}

输出结果:

图片 8

小结:

此时,LinkedHashSet中的元素是有序的

2.3 SortedSet(接口)

  • SortedSet是一个接口,里面(只有TreeSet这一个实现可用)的元素一定是有序的。

  • 保证迭代器按照元素递增顺序遍历的集合,

    可以按照元素的自然顺序(参见 Comparable)进行排序, 或者按照创建有序集合时提供的 Comparator进行排序

其源码如下:

public interface SortedSet<E> extends Set<E> {


    //返回与此有序集合关联的比较器,如果使用元素的自然顺序,则返回 null。

    Comparator<? super E> comparator();


    //返回此有序集合的部分元素,元素范围从 fromElement(包括)到 toElement(不包括)。

    SortedSet<E> subSet(E fromElement, E toElement);


    //用一个SortedSet, 返回此有序集合中小于end的所有元素。

    SortedSet<E> headSet(E toElement);


    //返回此有序集合的部分元素,其元素大于或等于 fromElement。

    SortedSet<E> tailSet(E fromElement);

    //返回此有序集合中当前第一个(最小的)元素。

    E first();
        

    //返回此有序集合中最后一个(最大的)元素

    E last();

}

2.4 TreeSet

  • TreeSet类实现Set 接口,该接口由TreeMap 实例支持,此类保证排序后的 set 按照升序排列元素,

    根据使用的构造方法不同,可能会按照元素的自然顺序 进行排序(参见 Comparable或按照在创建 set 时所提供的比较器进行排序。

  • Set 接口根据 equals 操作进行定义,但 TreeSet 实例将使用其 compareTo(或 compare)方法执行所有的键比较

代码实例TreeSetTest:

package cn.swum;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetTest {

    static class Person{

        int id;
        String name;
        int age;

        public Person(int id, String name, int age){
            this.id = id;
            this.name = name;
            this.age = age;

        }

        public String toString(){
            return "id:"+ this.id + " " + "name:" + this.name +" " + "age:" + this.age;

        }

    }


    static class MyComparator implements Comparator<Person> {

        @Override
        public int compare(Person p1, Person p2) {

            if(p1 == p2) {
                return 0;

            }

            if(p1 != null && p2 == null) {
                return 1;

            }else if(p1 == null && p2 != null){
                return -1;

            }

            if(p1.id > p2.id){
                return 1;

            }else if(p1.id < p2.id){
                return -1;

            }

            return 0;

        }

    }

    public static void main(String[] args) {
        MyComparator myComparator = new MyComparator();

        TreeSet<Person> treeSet = new TreeSet<>(myComparator);

        treeSet.add(new Person(3,"张三",20));
        treeSet.add(new Person(2,"王二",22));
        treeSet.add(new Person(1,"赵一",18));
        treeSet.add(new Person(4,"李四",29));

        //增加null空对象
        treeSet.add(null);

        System.out.println("TreeSet的排序是:");

        for (Person p : treeSet){
            if(p == null){
                System.out.println(p);
            }else {
                System.out.println(p.toString());
            }
        }

    }

}

实例用TreeSet保存对象引用,并且实现Comparator中compare方法进行比较和排序

输出结果:

图片 9

  • 表明TreeSet是可以按照自定义方法中的比较进行排序的,且可以有空值。

2.5 Vector

  • Vector 类也是基于数组实现的队列,代码与ArrayList非常相似。

  • 线程安全,执行效率低。

  • 动态数组的增长系数

  • 由于效率低,并且线程安全也是相对的,因此不推荐使用vector

2.6 Stack

Stack 是继承了Vector,是一个先进后出的队列

Stack里面主要实现的有一下几个方法:

方法名 返回类型 说明
empty boolean 判断stack是否为空
peek E 返回栈顶端的元素
pop E 弹出栈顶的元素
push E 将元素压入栈
search int 返回最靠近顶端的目标元素到顶端的距离

代码实例StackTest:

package cn.swum;

import java.util.Stack;

public class StackTest {

    static class Person{

        int id;
        String name;
        int age;

        public Person(int id, String name, int age){
            this.id = id;
            this.name = name;
            this.age = age;

        }

        public String toString(){
            return "id:"+ this.id + " " + "name:" + this.name +" " + "age:" + this.age;

        }

    }

    public static void main(String[] args) {

        Stack stack = new Stack();

        stack.push(new Person(1,"赵一",18));
        stack.push(new Person(2,"王二",19));
        stack.push(new Person(3,"张三",20));
        stack.push(new Person(4,"李四",21));

        System.out.println("栈顶元素是:(" + stack.peek() + ")");

        System.out.println("目标元素离栈顶多少距离:" + stack.search(stack.get(0)));

        System.out.println("栈元素从栈顶到栈底的排序是:");

        //此处先用size保存是因为pop时,size会减1,
        // 如果直接stack.size放在循环中比较,只能打印一半对象
        int size = stack.size();

        for (int i = 0; i < size ; i++) {

            Person p = (Person) stack.pop();

            System.out.println(p.toString());

        }

    }

}

输出结果:

图片 10

  • Stack 是一个有序的栈,遵循先进后出原则。

2.7 ArrayList

ArrayList是List的子类,它和HashSet相反,允许存放重复元素,因此有序。

集合中元素被访问的顺序取决于集合的类型。

如果对ArrayList进行访问,迭代器将从索引0开始,每迭代一次,索引值加1。

然而,如果访问HashSet中的元素,每个元素将会按照某种随机的次序出现。

虽然可以确定在迭代过程中能够遍历到集合中的所有元素,但却无法预知元素被访问的次序。

代码实例:ArrayListTest

package cn.swum;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ArrayListTest {

    public static void main(String[] args) {

        List<String> arrayList = new ArrayList<String>();


        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("c");
        //添加重复值
        arrayList.add("a");
        arrayList.add("d");
        arrayList.add("e");
        //添加null
        arrayList.add(null);

        System.out.println("arrayList的输出顺序为:");

        for (int i = 0; i < arrayList.size(); i++) {

            System.out.println((i+1) + ":" +arrayList.get(i));

        }

    }

}

输出结果:

图片 11

  • ArrayList是一个有序且允许重复和空值的列表

2.8 LinkedList

LinkedList是一种可以在任何位置进行高效地插入和删除操作的有序序列。

代码实例:LinkedListTest

package cn.swum;


import java.util.LinkedList;

/**
 * @author long
 * @date 2017/2/28
 */
public class LinkedListTest {

    public static void main(String[] args) {

        LinkedList<String> linkedList = new LinkedList<String>();

        linkedList.add("a");
        linkedList.add("b");
        linkedList.add("c");
        linkedList.add("d");
        linkedList.add("e");

        linkedList.add(2,"2");

        System.out.println("linkedList的输出顺序是:" + linkedList.toString());

        linkedList.push("f");

        System.out.println("push后,linkedList的元素顺序:" + linkedList.toString());

        linkedList.pop();

        System.out.println("pop后,linkedList的所剩元素:" + linkedList.toString());

    }

}

输出结果:

图片 12

  • LinkedList是有序的双向链表,可以在任意时刻进行元素的插入与删除,读取效率低于ArrayList,插入效率高

  • pop和push操作都是在队头开始

2.9 HashMap

  • HashMap的数据结构:

数组的特点是:寻址容易,插入和删除困难;

而链表的特点是:寻址困难,插入和删除容易。

哈希表结合了两者的优点。

哈希表有多种不同的实现方法,可以理解将此理解为“链表的数组”

图片 13

  • 从上图我们可以发现哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中:

    12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。然后每个线性的数组下存储一个链表,链接起来。

  • 首先HashMap里面实现一个静态内部类Entry,其重要的属性有 key , value,
    next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean.我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。

  • HashMap的存取实现:

//存储时:
int hash = key.hashCode();// 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
int index = hash % Entry[].length;
Entry[index] = value;

//取值时:
int hash = key.hashCode();
int index = hash % Entry[].length;
return Entry[index];
  • 疑问:如果两个key通过hash%Entry[].length得到的index相同,会不会有覆盖的危险?

这里HashMap里面用到链式数据结构的一个概念。上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry。打个比方,第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0]
= A。一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?

HashMap会这样做:B.next = A,Entry[0] =
B,如果又进来C,index也等于0,那么C.next = B,Entry[0] =
C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。也就是说数组中存储的是最后插入的元素。

HashMapTest代码实例,自我实现HashMap:

Entry.java

package cn.swum.cn.swun.hash;

/**
 * @author long
 * @date 2017/2/28
 */
public class Entry <K,V>{

    final K key;
    V value;
    Entry<K,V> next;//下一个结点

    //构造函数
    public Entry(K k, V v, Entry<K,V> n) {
        key = k;
        value = v;
        next = n;
    }

    public final K getKey() {
        return key;
    }

    public final V getValue() {
        return value;
    }

    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }

    public final boolean equals(Object o) {
        if (!(o instanceof Entry))
            return false;
        Entry e = (Entry)o;
        Object k1 = getKey();
        Object k2 = e.getKey();
        if (k1 == k2 || (k1 != null && k1.equals(k2))) {
            Object v1 = getValue();
            Object v2 = e.getValue();
            if (v1 == v2 || (v1 != null && v1.equals(v2)))
                return true;
        }
        return false;
    }

    public final int hashCode() {
        return (key==null   ? 0 : key.hashCode()) ^ (value==null ? 0 : value.hashCode());
    }

    public final String toString() {
        return getKey() + "=" + getValue();
    }

}

MyHashMap.java

package cn.swum.cn.swun.hash;

/**
 * @author long
 * @date 2017/2/28
 */
public class MyHashMap<K,V>{

    private Entry[] table;//Entry数组表
    static final int DEFAULT_INITIAL_CAPACITY = 16;//默认数组长度
    private int size;

    // 构造函数
    public MyHashMap() {
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        size = DEFAULT_INITIAL_CAPACITY;
    }

    //获取数组长度
    public int getSize() {
        return size;
    }

    // 求index
    static int indexFor(int h, int length) {
        return h % (length - 1);
    }

    //获取元素
    public V get(Object key) {
        if (key == null)
            return null;
        int hash = key.hashCode();// key的哈希值
        int index = indexFor(hash, table.length);// 求key在数组中的下标
        for (Entry<K, V> e = table[index]; e != null; e = e.next) {
            Object k = e.key;
            if (e.key.hashCode() == hash && (k == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

    // 添加元素
    public V put(K key, V value) {
        if (key == null)
            return null;
        int hash = key.hashCode();
        int index = indexFor(hash, table.length);

        // 如果添加的key已经存在,那么只需要修改value值即可
        for (Entry<K, V> e = table[index]; e != null; e = e.next) {
            Object k = e.key;
            if (e.key.hashCode() == hash && (k == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                return oldValue;// 原来的value值
            }
        }
        // 如果key值不存在,那么需要添加
        Entry<K, V> e = table[index];// 获取当前数组中的e
        table[index] = new Entry<K, V>(key, value, e);// 新建一个Entry,并将其指向原先的e
        return null;
    }

}

MyHashMapTest.java

package cn.swum.cn.swun.hash;

/**
 * @author long
 * @date 2017/2/28
 */
public class MyHashMapTest {

    public static void main(String[] args) {

        MyHashMap<Integer, Integer> map = new MyHashMap<Integer, Integer>();
        map.put(1, 90);
        map.put(2, 95);
        map.put(17, 85);

        System.out.println(map.get(1));
        System.out.println(map.get(2));
        System.out.println(map.get(17));
        System.out.println(map.get(null));
    }

}

输出结果:

图片 14

2.10 WeekHashMapTest

package cn.swum.cn.swun.hash;

import java.util.WeakHashMap;

/**
 * @author long
 * @date 2017/2/28
 */
public class WeekHashMapTest {

    public static void main(String[] args) {
        int size = 10;

        if (args.length > 0) {
            size = Integer.parseInt(args[0]);
        }

        Key[] keys = new Key[size];
        WeakHashMap<Key, Value> whm = new WeakHashMap<Key, Value>();

        for (int i = 0; i < size; i++) {
            Key k = new Key(Integer.toString(i));
            Value v = new Value(Integer.toString(i));
            if (i % 3 == 0) {
                keys[i] = k;//强引用
            }
            whm.put(k, v);//所有键值放入WeakHashMap中
        }

        System.out.println(whm);
        System.out.println(whm.size());
        System.gc();

        try {
            // 把处理器的时间让给垃圾回收器进行垃圾回收
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(whm);
        System.out.println(whm.size());
    }
}

class Key {
    String id;

    public Key(String id) {
        this.id = id;
    }

    public String toString() {
        return id;
    }

    public int hashCode() {
        return id.hashCode();
    }

    public boolean equals(Object r) {
        return (r instanceof Key) && id.equals(((Key) r).id);
    }

    public void finalize() {
        System.out.println("Finalizing Key " + id);
    }
}

class Value {
    String id;

    public Value(String id) {
        this.id = id;
    }

    public String toString() {
        return id;
    }

    public void finalize() {
        System.out.println("Finalizing Value " + id);
    }

}

输出结果:

图片 15

2.11 HashTable与HashMap的区别

  • HashTable和HashMap存在很多的相同点,但是他们还是有几个比较重要的不同点。

Java集合类 1.简介:
java集合类包含在java.util包下 集合类存放的是对象的引用,而非对象本身。
集合类型主要分为Set(集…

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图