关于集合框架的基本的介绍(JDK7)

集合框架中的接口以及继承关系

  关于集合框架中的接口,注意下面列出的全都是接口:

clip_image001[7]


  接口与具体的实现类蓝色表示接口橙色表示具体实现类(仅仅列出比较常用的一些):

clip_image001[9]

  这个图是一个具体的集合框架的接口以及实现类的图,可以和上面的全部接口相对应:

clip_image005

  因为collection有很多的子类,为了操作方便,并没有哪个类直接实现了collecion接口,而是直接对collection接口进行继承,仅仅是提供了更加具体的子接口。

关于List

ArrayList的基本使用:
package com.javase.collection;

import java.util.ArrayList;
import java.util.LinkedList;

public class testList {
    public static void main(String[] args) {
        //最好是通过泛型的方式来使用 负责取出元素的时候还需要进行强制类型转化
        ArrayList<String> list=new ArrayList<String>();
        //通过append的方式进行追加
        list.add("abc");
        list.add("def");
        list.add("ghi");
        list.add("jkl");
        //获得固定下标的元素
        String a=list.get(0);
        int s=list.size();
        System.out.println("the size is "+s);
        for(int i=0;i<s;i++)
        {
            System.out.println(list.get(i));
        }
        //判断某个元素的索引
        System.out.println("the index of abc is "+ list.indexOf("def"));
        //删除固定索引的元素
        list.remove(0);
        System.out.println("after the remove option the first element is "+ list.get(0));

        //转化为一个数组 
        //这里要是写成 String [] str=(String [])list.toArray();在执行的时候就会抛出异常
        //只能在使用的时候 先取出一个个 Object对象 再进行强制转化 
        //因为仅仅是String Integer等等这些类型继承了Object 而String[] Integer[]并没有继承Object[]
        //因此这里只能使用Object[]来进行强制类型转化 使用别的就会报错
        Object [] str=(Object [])list.toArray();
        System.out.println("--------------------");
        for(int i=0;i<str.length;i++)
        {
            System.out.println(str[i]);
        }
        LinkedList linklist=new LinkedList();
        //直接可以将其他的集合类型作为参数传入 生成一个ArrayList
        ArrayList list3=new ArrayList(linklist);
        //clear清除全部内容
        list.clear();
        System.out.println("after clear option the size is "+list.size());

    }

}


输出结果:
the size is 4
abc
def
ghi
jkl
the index of abc is 1
after the remove option the first element is def
--------------------
def
ghi
jkl
after clear option the size is 0

关于ArrayList源码的简要分析:

  类的声明的结构如下

  public class ArrayList<E> extends AbstractList<E>

  implements List<E>, RandomAccess, Cloneable, java.io.Serializable

  注意看整个ArrayList类声明的时候就是通过泛型的方式来进行的

  一共有三个构造方法:

  第一个是通过声明一个capacity

  可以看到在构造函数中 关键的部分是:

  this.elementData = new Object[initialCapacity];

  其中elementData是个Object类型的数组 初始的时候,实际ArrayList的底层是通过这个Object类型的数组来维护的。

  第二个是没有参数的形式

public ArrayList() {

this(10);

}

  可以看到这段,要是不指定capacity的话,ArrayList底层默认生成一个capacity为10的数组。

  第三个是通过传入另外一个集合框架 将其中的内容转化成为一个ArrayList

  比如可以生成一个LinkedList 对象 将其作为形参传入 生成ArrayList

关于add方法

  注意添加新元素之前要对集合的siz+1进行检测,保证当前底层的Object数组的空间是足够的,这一步通过ensureCapacityInternal(size + 1);这个函数来进行,够的话就直接放入,size增加1,要是不够的话会通过调整newCapacity来继续进行,调整之后将原来的元素拷贝到一个新的Object数组中,数组空间大小为newCapacity(通过Arrays.copyof来进行):

  elementData = Arrays.copyOf(elementData, newCapacity);

  还可以添加参数,将元素插入到指定的位置,但这种方式需要将插入位置后面的部分都进行移动,代价比较高通过这个函数来进行:

  System.arraycopy(elementData, index, elementData, index + 1,

size - index);

  函数原型声明:(void java.lang.System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length))

关于remove方法

  这个其实与上面在固定位置插入元素的操作很相似,只不过拷贝的方式是向前进行的。

  由于ArrayList的底层就是一个Object数组,因此在固定位置上的插入和删除操作代价都是比较高的。

关于LinkedList

  这个也算是数据结构中最基本的了,就是链表的结构,根据链表自身的结构特性,比起ArrayList又有一些特殊的方法,比如头插addFirst 尾插 addLast。

  当然LinkedList底层肯定维护的是一个链表,不想ArrayList那样维护一个数组,这个是结点Node 的部分,是一个用泛型来实现的静态内部类,内容就是我们通常意义上的具体元素值,前驱指针,后继指针:

private static class Node<E> {

E item;

Node<E> next;

Node<E> prev;

Node(Node<E> prev, E element, Node<E> next) {

this.item = element;

this.next = next;

this.prev = prev;

}

}

  具体的插入删除操作都与通常数据结构书中介绍的内容类似。

  还是那些老生常谈的问题,再注意一下,也就是线性表和链表的区别,插入删除操作的时候用LinkedList比较快,指定位置检索元素的时候用ArrayList比较快。

关于Set的机制

Hashcode与equals方法的补充说明

  首先要再对hashcode 以及equal方法再进一步进行说明,之前的一些说明可以参(http://www.cnblogs.com/Goden/p/3990985.html)。

进一步补充:

  hashcode的一般要求:

  1、 一致性,同一个对象的hashcode方法被多次调用之后应当返回一样的值(前提是该对象的内容没有发生变化)

    2、 两个对象a,b,如果a.equals(b)返回的是true,则对象a和b的hashcode值要是相同的。

  3、 两个对象 a,b 如果a.equals(b)返回的是false,则对象 a 和 b 的hashcode不要求一定相同,即使说在hashcode相同的时候,a.equals(b)不一定是true,也可以是false。

  对于Object类,其hashcode表示的是对象的地址,因此不同Object实例,其对象是不同的。

  一般一个自定义的类的equal方法重写之后,对应的hashcode方法也需要进行重写,这是为了保证通过equal比较相等的对象有相同的hashcode。

  当使用HashSet的时候,若是增加一个元素,则会判断已经存在集合中的所有元素的hashcode的值是否与增加的这个元素的hashcode的值是一致的。如果不一致,则将这个元素加进去。如果与某个对象一致(hashcode一样),按照前面的描述,这个时候equals方法还有可能返回的是false于是再进行equals方法的调用,若和这个对象进行比较,若equals返回为true,说明这个元素已经加入集合,就不再进行添加了。若equals返回为 false,说明这个元素还没有加入到集合中(就是那种hashcode相同而equals不相同的情况)Hashcode相同而equals不同的例子可能不太好想到,比如下面这个:

package com.testcollection;

import java.util.HashSet;

class People{
    String name;
    public People(String name){
        this.name=name;
    }
}

public class testHashcode {
    public static void main(String[] args) {
        HashSet<People> set=new HashSet<People>();
        //这两次添加就成功了 因为按照object类的hashcode和equal方法 这个是两个不同的
        //但实际上里面的内容是相同的
        set.add(new People("abc"));
        set.add(new People("abc"));
        //像这种情况 虽然两个类的hashcode并不相同 根据打印结果就能看出来 默认的toString方法 在@后面 就是hashcode值 但是实际上他们的内容是一样的
        //属性的情况比较复杂的话 就不能满足需求了
        //这种情况下 Object类中的hashcode与equals方法就不能满足实际的需要了 需要重写
        System.out.println(set);
        
        People p1=new People("def");
        System.out.println(set.add(p1));
        //这个添加就失败了
//这里两次添加的都是p1指针指向的是同一个对象 不像是上面那种情况 指向的是不同的两个对象(虽然对象的内容是相同的 但是是生成了两次的)
System.out.println(set.add(p1)); } } /* 打印结果 [com.testcollection.People@55fe910c, com.testcollection.People@3be4d6ef] true false */

  实际情况下,应当对Person中的hashcode和equals方法进行重写,hashcode就直接用属性的hashcode,而equals方法则参照Object类中的equals方法来实现具体可以参考(http://www.cnblogs.com/Goden/p/3990985.html

  下面就是重写的例子:

package com.test.collection;

import java.util.HashSet;

public class testHashcode {

    public static void main(String[] args) {
        HashSet<People> set=new HashSet<People>();
        System.out.println(set.add(new People("abc")));
        //由于重写了people类的hashcode 以及equals方法 第二次插入就会返回false 插入失败
        System.out.println(set.add(new People("abc")));

    }
}

class People {
    String name;

    public People(String name) {
        this.name = name;
    }

    public int hashCode() {
        return this.name.hashCode();
    }

    public boolean equals(Object obj) {
        boolean b = false;

        if (this == obj) {
            b = true;
        }
        if (null != obj && obj instanceof People) {
            People p = (People) obj;

            if (name.equals(p.name)) {
                b = true;
            } else {
                b = false;
            }
        }

        return b;
    }
}

  实际开发中对于hashcode以及equals方法的重写通常是需要通过一一比较类中的内容,这样进行下去。由于实际情况中这个用的还是比较普遍,通常直接在编译器的source->generate equals and hashcode的操作这样就能继续往下进行。

迭代器

  各个集合的实现都有一个iterator()方法,这个方法主要是用来返回一个迭代器。

  迭代器的最顶层就是一个用泛型来实现的public interface Iterator<E>接口,方法也比较简单,主要有三个:hasNext Next 以及remove。

  hasNext表示集合中是否还有更多的元素,如果集合中还有更多元素的话,这个结果就返回true,要是没有更多元素的话,就返回false

Next 表示返回下一个元素,注意每次调用了Next之后,要执行两个操作:返回下一个元素,以及往后跳动一个位置。remove 这个是用于安全地删除集合中的元素,具体的集合的实现类一般都对这个方法进行了不同的实现。

通常用到的是前两个方法。

下面是一个简要的逻辑图,便于理解next以及hasnext,注意初始的时候:

clip_image001[11]

  由于每个集合框架都对这个Iterator接口有具体的实现,实际中也要是通过iterator函数返回一个iterator迭代器,之后通过这个迭代器来遍历集合当中的每个元素,这样一次可以返回一个元素,通常使用一个循环来遍历集合中的每个元素,格式比较固定,主要是三步:调用iterator方法得到迭代函数,建立hasNext()循环迭代,只要返回值为true就继续进行,在循环内部通过next方法得到下一个的元素(指针会同时后移)。

  下面是一个基本的例子,对应的写法要掌握:

package com.test.collection;

import java.util.HashSet;
import java.util.Iterator;

public class testIterator {
    public static void main(String[] args) {
        HashSet<Integer> set=new HashSet<Integer>();
        for(int i=0;i<=10;i++){
            set.add(i);
        }
        //通过迭代的方式遍历集合 打印出集合中全部元素
        for(Iterator<Integer> iter=set.iterator();iter.hasNext();){
            System.out.println(iter.next());
        }
    }
}
关于HashSet与TreeSort

  通过名称也比较好理解,HashSet就是最直接的Set的机制,最后输出的话,输出元素的顺序是凌乱的而且每次输出的时候都不一样,TreeSet就是集合+排序,里面的元素在每次添加的时候都是自动排好序的,TreeSet实现了SortedSet的接口,里面元素的顺序是有序的,输出的时候就是按序输出的。注意定义TreeSet的时候,如果里面的元素是非原始的数据类型,一定要传入一个自定义的比较器,要不然就没法往TreeSet中放元素,一定要先通过TreeSet来指定好元素的比较顺序。

package com.test.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;

public class testIterator {
    public static void main(String[] args) {
        HashSet<Integer> set=new HashSet<Integer>();
        TreeSet<Integer> treeset=new TreeSet<Integer>();
        for(int i=100;i>=1;i--){
            set.add(i);
            treeset.add(i);
        }
        //通过迭代的方式遍历集合 打印出集合中全部元素 这个输出就是无序的
        for(Iterator<Integer> iter=set.iterator();iter.hasNext();){
            System.out.println(iter.next());        
        }
        //放到TreeSet里面的输出就是有序的 默认是从小到大的
        for(Iterator<Integer> siter=treeset.iterator();siter.hasNext();){
            System.out.println(siter.next());        
        }
    }
}
关于Comparator接口

  由于TreeSet实现了SortedSet接口,每次新加入进来的元素都是有序存放的,这里就涉及到了排序的问题。

  就像C++的sort的实现一样,如果是自定义的排序问题的话,特别是对于结构话的数据进行比较,需要引入一个Comparator接口,在声明集合的时候将比较器传入。这个接口中有一个compare方法,自定义的比较器实现了这个接口之后再传入TreeSort中就可以按照自定义的模式进行比较了。

  注意compare方法的返回类型是int类型,按照自定义的比较方式,如果:

  第一个参数小于第二个参数 返回一个负数

  第一个参数等于第二个参数 返回0

  第一个参数大于第二个参数 返回一个正数

  下面是一个基本的在定义TreeSet集合的时候使用自定义Comparator构造器的例子:

package com.test.tempTest;

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

class Person {
    int id;
    String name;

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

class Mycompare implements Comparator<Person> {

    // sorted by name increasing
    public int compare(Person p1, Person p2) {

        int result = p1.getName().compareTo(p2.getName());
        if (result == 0) {
            result = p1.getId() - p2.getId();
        }
        return result;
    }

}

public class testbasicComparator {
    public static void main(String[] args) {
        // 声明的时候可以传入一个实现了comparator接口的类作为自定义比较器
        TreeSet<Person> treeset = new TreeSet<Person>(new Mycompare());
        treeset.add(new Person(1, "dfe"));
        treeset.add(new Person(2, "efd"));
        treeset.add(new Person(3, "abc"));
        treeset.add(new Person(4, "dfe"));
        // 通过迭代器输出
        for (Iterator<Person> iter = treeset.iterator(); iter.hasNext();) {
            Person p = iter.next();
            System.out.println("the name is: " + p.getName() + " the id is "
                    + p.getId());
        }
    }
}

/*
输出结果如下,可以看出来结果符合Comparator中定义的顺序:
the name is: abc the id is 3
the name is: dfe the id is 1
the name is: dfe the id is 4
the name is: efd the id is 2
*/
关于Collections类

  Arrays类是数组方法的工具类,里面提供的许多对于数组操作的静态方法。类似地Collections是一个集合的工具类,里面提供了许多对于集合的操作的静态方法,操纵的目标是集合对象,为集合对象提供辅助的方法,比如最基本的sort方法可以提供实现了List接口的集合的排序。

    还有一些比较常用到的辅助函数:
    比如Collections.shuffle(List<E>list)这个主要功能是将list中元素的顺序弄乱,在快速排序的时候,用这个可以避免最差的那种情况,来提升效率。

  还有就是Collections.min(List<E>list)以及Collections.max(List<E>list)用于返回序列中的最大和最小的元素。

    整个Comparator就是基于策略模式实现的,下面是一个基于策略模式实现的比较的例子:一个Person类中有id,name,age三个属性,通过泛型来自定义一个比较器,通过策略模式来传入一种sort策略,进行排序。

//首先是一个基本的Person类
package com.test.collector;

public class Person {
       int id;
       int age;
       String name;
    
    public Person(int id, int age, String name) {
        super();
        this.id = id;
        this.age = age;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    //注意重写hashcode以及equals方法
    //这里可以通过eclispe来自动生成
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
       
}

//Sort接口:
package com.test.collector;

import java.util.List;

public interface Sort {
    public void sort(List<Person> list);
}

//Sort接口的两种实现,同时实现了Comparator接口:
package com.test.collector;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

//这里同时还要实现comparator接口
public class upNameSort implements Sort,Comparator<Person> {

    public void sort(List<Person> list) {
        //通过collections工具类的sort方法来进行排序
        Collections.sort(list,this);

    }


    public int compare(Person p1, Person p2) {
        int result=p1.getName().compareTo(p2.getName());
        //根据id来进行
        if(result==0){
            result=p1.getId()-p2.getId();
        }
        return result;
    }

}

package com.test.collector;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class upIdSort implements Sort,Comparator<Person> {


    public void sort(List<Person> list) {
        Collections.sort(list, this);
        
    }


    public int compare(Person p1, Person p2) {
        int result=p1.getId()-p2.getId();
        return result;
    }

}

//通过这个类来体现策略模式 通过传入的way参数来调用不同的方式进行排序:
package com.test.collector;

import java.util.List;

public class SortWay {
    private Sort dosort;
    private int way;

    public Sort getDosort() {
        return dosort;
    }

    public void setDosort(Sort dosort) {
        this.dosort = dosort;
    }

    public void doSort(List<Person> list, int way) {
        if (way == 1) {
            this.dosort = new upIdSort();
            dosort.sort(list);
        }
        if (way == 2) {
            this.dosort = new upNameSort();
            dosort.sort(list);
        }

    }

}

//Client类 用于进行实际的测试:
package com.test.collector;

import java.util.ArrayList;
import java.util.Iterator;

public class Client {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<Person>();
        list.add(new Person(4, 23, "abc"));
        list.add(new Person(2, 24, "cdf"));
        list.add(new Person(3, 25, "fgr"));
        list.add(new Person(1, 26, "abc"));

        SortWay sw = new SortWay();
        // 此时是按照id排序
        sw.doSort(list, 1);

        for (Iterator<Person> iter = list.iterator(); iter.hasNext();) {
            Person p = iter.next();
            System.out.println("the name is :" + p.getName() + " the id is :"
                    + p.getId());
        }

        System.out.println("--------------------------");
        sw = new SortWay();
        // 此时是按照name排序
        sw.doSort(list, 2);

        for (Iterator<Person> iter = list.iterator(); iter.hasNext();) {
            Person p = iter.next();
            System.out.println("the name is :" + p.getName() + " the id is :"
                    + p.getId());
        }
    }
}

/*
输出结果:
the name is :abc the id is :1
the name is :cdf the id is :2
the name is :fgr the id is :3
the name is :abc the id is :4
--------------------------
the name is :abc the id is :1
the name is :abc the id is :4
the name is :cdf the id is :2
the name is :fgr the id is :3

上面是按照id进行排序 下面是按照name字典顺序进行的排序
*/

关于Map的机制

关于map的基本概念

    Map<K,V>数据结构主要用于表示一个key<—>value的键值对,key与value可以是通过泛型来定义的不同的数据类型,他们之间的的关系是一一对应的,一个key映射到一个value值上,但是所有的Key值是不可以重复的,如果add相同的key值,但是value不同的键值对进入map,貌似后插入的一个key-value值会将先前的key-value值覆盖掉,最后只存最后的key-value值。

    通常使用的就是HashMap,就像HashSet一样,存入进来的键值对再取出的时候是乱序的。

    放入的时候直接map.put(“key”,”value”)取value值的时候通过key值来作为索引取出,比如取出一个String类型的value,String value=map.get(“key”)。(注意在map中是使用put而不是使用add)

    关于迭代输出的时候通常有两种方法:

    1、 通过返回map中所有key的集合(set类型),再依次通过map.get(“key”)取出所有的value的值。

    2、 通过返回一个entry结构的集合(Map中的一个内部类,这个类中维护了key value的信息)具体见下面的源码分析

    下面是一个Map基本操作的例子:

package com.test.testMap;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

public class basicMap {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("a", "aa");
        map.put("b", "bb");
        map.put("c", "cc");
        map.put("d", "aa");
        // 加入了key相同的键值对 后加入的一个先加入的一个键值对替代掉
        map.put("a", "bb");

        // 通过key的集合来迭代
        Set<String> set = map.keySet();
        for (Iterator<String> iter = set.iterator(); iter.hasNext();) {
            String key = iter.next();
            String value = map.get(key);
            System.out
                    .println("the key is :" + key + " the value is :" + value);
        }

        System.out.println("--------------------");
        // 通过第二种方式进行迭代 通过返回一个Entry的集合来进行
        Set<Entry<String, String>> entryset = map.entrySet();
        for (Iterator<Entry<String, String>> entryiter = entryset.iterator(); entryiter
                .hasNext();) {
            Entry<String, String> e = entryiter.next();
            String key = e.getKey();
            String value = e.getValue();
            System.out
                    .println("the key is :" + key + " the value is :" + value);
        }
    }
}
/*
输出的结果如下,可以看出来后加进来的关键字相同的(a,bb)键值对代替了最开始输入的的(a,aa)键值对。


the key is :d the value is :aa
the key is :b the value is :bb
the key is :c the value is :cc
the key is :a the value is :bb
------------------------------
the key is :d the value is :aa
the key is :b the value is :bb
the key is :c the value is :cc
the key is :a the value is :bb
*/
关于HashSet以及HashMap的简要源码分析

    HashSet的底层是由HashMap来实现的,只是从逻辑上来看的话,就抽象成了一个HashSet,事实上在HashSet的源码中:

    属性值中有这个:

    private transient HashMap<E,Object> map;

    默认的构造函数是这个:

    public HashSet() {

    map = new HashMap<>();

    }

    可以看出来Set的本质就是一个Map,只不过这Set中的值就是这个Map中的key值,这个Map中的Value值并没有实际的意义,只是用一个Object来占个位置就好了。逻辑上看成是一个Set类型,实际底层使用Map类型来实现的。当一个元素被放入HashSet中的时候,实际上这个元素是被放入了底层所维护的HashMap的key中,而他们的value值全都是一个Objec对象,并没有什么实际的意义,只起到占位的作用,这个对象在我们对Set进行操作的相关过程中并不会用到。

    实际上只要把HashMap分析清楚就相当于把HashSet一起分析了。

    先看HashSet中维护了静态类:

    static class Entry<K,V> implements Map.Entry<K,V>

    这个类里面维护了一个Key Value键值对的信息,以及其他的相关信息(指向下一个Entry结点的指针)。

    在类的属性中有一个table表,实际上就是一个Entry的数组:

    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

    其中EMPTY_TABLE初始的时候是一个空的ENTRY数组:

    static final Entry<?,?>[] EMPTY_TABLE = {};

    具体的代码没有一句一句来分析,只是把主要的思想记录下来,主要是分析在put一个键值对进入的时候具体都执行了哪些操作:

   向HashMap中put一个键值对的时候,先对空间进行检查,如果之前table是空的,就重新为table数组分配空间,之后通过hash函数进行hash地址的计算(这里用到了比较多的移位的操作),就像通常数据结构中介绍的那样,计算出散列地址,之后进行冲突处理。

    这里对于冲突的处理方式是采用链地址法,每次散列到了一个新的地址,就会采用头插法,如果新的键值对与旧的键值对有相同的key值和不同的value值,后面的value值将会把之前的value值替换掉。如果新的键值对与旧的键值对仅仅是hash地址相同但key值是不同的,就是发生的地址冲突的情况,就用头插大将将新的Entry结点插入到当前的位置(最近被调用的再次被调用的几率比较大),当前新的Entry结点的next指针会指向旧的Entry结点。

    在这个过程中还要涉及到table数组的重新复制以及扩容(扩容的阈值是通过之前指定的负载因子来控制的)。

其他

    可能还有一些框架比如Vector这个基本上被ArrayList代替了,它们实现的功能大致也是相同的,类似地,HashTable也被HashMap代替了,它们也实现的是类似的功能,貌似它们之间主要的区别是线程安全问题,HashTable是线程安全的,其中的许多方法都是Synchonized的HashMap不是线程安全的,但在单线程的环境下,性能比HashTable要好,具体的还没有去深究。

原文地址:https://www.cnblogs.com/Goden/p/4024798.html