JavaSE学习笔记(五):集合

目录

一、集合框架的概述

二、集合框架涉及到的API

三、Collection

Collection接口中的常用方法

Iterator迭代器接口

Iterator的使用方法

foreach循环遍历集合或数组(JDK5.0以后)

1、List(存储有序的、可重复的数据。)

常用方法

1、ArrayList(List 接口的典型实现类、主要实现类)

2、LinkedList

3、Vector(古老实现类)

2、Set(存储无序的、不可重复的数据。)

 Set接口实现类

1、HashSet

2、LinkedHashSet

3、TreeSet

四、Map

Map存储结构的理解

Map中的常用方法

Map中key、value和key-value的遍历实现

1、HashMap(Map接口使用频率最高的实现类)

 1.1HashMap在jdk7中实现原理

1.2HashMap在jdk8中相较于jdk7在底层实现方面的不同

1.3 HashMap底层典型属性的属性说明

2、LinkedHashMap

2.1LinkedHashMap的底层实现原理(了解)

3、TreeMap

4、Hashtable(古老实现类)

5、Properties

五、工具类Collections

作用

Collections常用方法

 面试题

最后


一、集合框架的概述

一、集合框架的概述
1.集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(. txt,x jpg,avi,数据库中
2.1数组在存储多个数据方面的特点:
>一旦初始化以后,其长度就确定了。
>数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。
比如:String[]arr;int[]arri]:0bject[]arr2;
2.2数组在存储多个数据方面的缺点;
>一旦初始化以后,其长度就不可修改。
>数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
>获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用于
>数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。

二、集合框架涉及到的API

/**
 *      &---Collection接口:单列集合,用来存储一个一个的对象
 *                  &---List接口:存储有序的、可重复的数据。  -->“动态”数组
 *                      &---ArrayList、LinkedList、Vector
 *
 *                  &---Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
 *                      &---HashSet、LinkedHashSet、TreeSet
 *
 *      &---Map接口:双列集合,用来存储一对(key - value)一对的数据   -->高中函数:y = f(x)
 *          &---HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
 */

三、Collection

Collection接口中的常用方法

1、添加

                add(Objec tobj)
                addAll(Collection coll)
2、获取有效元素的个数
                int size()
3、清空集合
                void clear()
4、是否是空集合
                boolean isEmpty()
5、是否包含某个元素
                boolean contains(Object obj):是通过元素的equals方法来判断是否是同一个对象
                boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。
6、删除
                boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
                boolean removeAll(Collection coll):取当前集合的差集

7、取两个集合的交集
                boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c
8、集合是否相等
                boolean equals(Object obj)
9、转成对象数组
                Object[] toArray()
10、获取集合对象的哈希值
                hashCode()
11、遍历
                iterator():返回迭代器对象,用于集合遍历

Iterator迭代器接口

        Iterator对象称为迭代器(设计模式的一种),主要用于遍历Collection 集合中的元素。
        GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。类似于“公交车上的售票员”、“火车上的乘务员”、“空姐”。
        Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
        Iterator 仅用于遍历集合,Iterator本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
        集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

Iterator的使用方法

import org.testng.annotations.Test;

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

/**
 * 集合元素的遍历操作,使用迭代器Iterator接口
 * 内部的方法:hasNext()和 next()
 *
 */
public class IteratorTest {

    @Test
    public void test(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        Iterator iterator = coll.iterator();

        //方式一:
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        //报异常:NoSuchElementException
//        //因为:在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常。
//        System.out.println(iterator.next());

        //方式二:不推荐
//        for(int i = 0;i < coll.size();i++){
//            System.out.println(iterator.next());
//        }

        //方式三:推荐
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

foreach循环遍历集合或数组(JDK5.0以后)

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;

/**
 * jdk 5.0 新增了foreach循环,用于遍历集合、数组
 *
 */
public class ForTest {

    @Test
    public void test(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        //for(集合元素的类型 局部变量 : 集合对象),内部仍然调用了迭代器。
        for(Object obj : coll){
            System.out.println(obj);
        }
    }

    @Test
    public void test2(){
        int[] arr = new int[]{1,2,3,4,5,6};
        //for(数组元素的类型 局部变量 : 数组对象)
        for(int i : arr){
            System.out.println(i);
        }
    }

    //练习题
    @Test
    public void test3(){
        String[] arr = new String[]{"SS","KK","RR"};

//        //方式一:普通for赋值
//        for(int i = 0;i < arr.length;i++){
//            arr[i] = "HH";
//        }

        //方式二:增强for循环
        for(String s : arr){
            s = "HH";
        }

        for(int i = 0;i < arr.length;i++){
            System.out.println(arr[i]);
        }
    }
}

1、List(存储有序的、可重复的数据。)

常用方法

>void add(intindex, Object ele):在index位置插入ele元素
>boolean addAll(int indaex, Collection eles):从index位置开始将eles中的所有元素添加进来
>Object get(int index):获取指定index位置的元素
>int indexOf(Object obj):返回obj在集合中首次出现的位置
>int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
>Object remove(int index):移除指定index位置的元素,并返回此元素
>Object set(int index, Object ele):设置指定index位置的元素为ele
>List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合

1、ArrayList(List 接口的典型实现类、主要实现类)

/**
 * ArrayList的源码分析:
 *   1.1 jdk 7情况下
 *      ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
 *      list.add(123);//elementData[0] = new Integer(123);
 *      ...
 *      list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
 *      默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
 *
 *      结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)
 *
 *   1.2 jdk 8中ArrayList的变化:
 *      ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组
 *
 *      list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
 *      ...
 *      后续的添加和扩容操作与jdk 7 无异。
 *   1.3 小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象
 *            的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
 *
 */

2、LinkedList

  • 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
  • LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。
/**
  * 3.LinkedList的源码分析:
  *       LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
  *       list.add(123);//将123封装到Node中,创建了Node对象。
  *
  *       其中,Node定义为:体现了LinkedList的双向链表的说法
  *       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;     //next变量记录下一个元素的位置
  *            this.prev = prev;     //prev变量记录前一个元素的位置
  *            }
  *        }
  */

/**
  * 3.LinkedList的源码分析:
  *       LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
  *       list.add(123);//将123封装到Node中,创建了Node对象。
  *
  *       其中,Node定义为:体现了LinkedList的双向链表的说法
  *       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;     //next变量记录下一个元素的位置
  *            this.prev = prev;     //prev变量记录前一个元素的位置
  *            }
  *        }
  */

3、Vector(古老实现类)

Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。
在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。

Vector的源码分析:jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。  在扩容方面,默认扩容为原来的数组长度的2倍。

2、Set(存储无序的、不可重复的数据。)

  • Set接口是Collection的子接口,set接口没有提供额外的方法
  • Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。
  • Set 判断两个对象是否相同不是使用==运算符,而是根据equals()方法

 Set接口实现类

/**
 * 1.Set接口的框架:
 * |----Collection接口:单列集合,用来存储一个一个的对象
 *          |----Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
 *             |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
 *                 |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历
 *                                    对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
 *             |----TreeSet:可以按照添加对象的指定属性,进行排序。
 */

1、HashSet

/**
     * 一、Set:存储无序的、不可重复的数据
     *      1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。
     *
     *      2.不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个。
     *
     * 二、添加元素的过程:以HashSet为例:
     *      我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,
     *      此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断
     *      数组此位置上是否已经有元素:
     *          如果此位置上没有其他元素,则元素a添加成功。 --->情况1
     *          如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
     *              如果hash值不相同,则元素a添加成功。--->情况2
     *              如果hash值相同,进而需要调用元素a所在类的equals()方法:
     *                    equals()返回true,元素a添加失败
     *                    equals()返回false,则元素a添加成功。--->情况2
     *
     *      对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储。
     *      jdk 7 :元素a放到数组中,指向原来的元素。
     *      jdk 8 :原来的元素在数组中,指向元素a
     *      总结:七上八下
     *
     * HashSet底层:数组+链表的结构。
     *
     */

2、LinkedHashSet

LinkedHashSet是HashSet的子类
LinkedHashSet根据元素的hashCode值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
LinkedHashSet插入性能略低于HashSet,但在迭代访问Set 里的全部元素时有很好的性能。
LinkedHashSet不允许集合元素重复。

3、TreeSet

TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
TreeSet底层使用红黑树结构存储数据
新增的方法如下:(了解)
        Comparator comparator()
        Object first()
        Object last()
        Object lower(Object e)
        Object higher(Object e)
        SortedSet subSet(fromElement, toElement)
        SortedSet headSet(toElement)
        SortedSet tailSet(fromElement)
TreeSet两种排序方法:自然排序和定制排序。默认情况下,TreeSet采用自然排序。
TreeSet和后面要讲的TreeMap采用红黑树的存储结构
特点:有序,查询速度比List快
自然排序:TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。
》如果试图把一个对象添加到TreeSet时,则该对象的类必须实现Comparable 接口。
实现Comparable 的类必须实现compareTo(Object obj)方法,两个对象即通过compareTo(Object obj)方法的返回值来比较大小。
Comparable 的典型实现:
        BigDecimal、BigInteger以及所有的数值型对应的包装类:按它们对应的数值大小进行比较
        Character:按字符的unicode值来进行比较
        Boolean:true 对应的包装类实例大于false 对应的包装类实例
        String:按字符串中字符的unicode 值进行比较
        Date、Time:后边的时间、日期比前面的时间、日期大
向TreeSet中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。
》因为只有相同类的两个实例才会比较大小,所以向TreeSet中添加的应该是同一个类的对象。
对于TreeSet集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj)方法比较返回值。
当需要把一个对象放入TreeSet中,重写该对象对应的equals()方法时,应保证该方法与compareTo(Object obj) 方法有一致的结果:如果两个对象通过equals()方法比较返回true,则通过compareTo(Object obj)方法比较应返回0。否则,让人难以理解。

四、Map

Map:双列数据,存储key-value对的数据---类似于高中的函数:y=f(x)

Map存储结构的理解

Map中的key:无序的、不可重复的,使用Set存储所的key--->key所在的类要重写equals()和hash Code()(以HashMap为例)
Map中的value:无序的、可重复的,使用 collection 存储所的value--->value所在的类要重写equals()

一个键值对:key-value构成了一个Entry对象。
Map中的entry:无序的、不可重复的,使用Set存储所用的entry

Map中的常用方法

import org.junit.Test;

import java.util.*;
/**
 *  五、Map中定义的方法:
 *      添加、删除、修改操作:
 *      Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
 *      void putAll(Map m):将m中的所有key-value对存放到当前map中
 *      Object remove(Object key):移除指定key的key-value对,并返回value
 *      void clear():清空当前map中的所有数据
 *      元素查询的操作:
 *      Object get(Object key):获取指定key对应的value
 *      boolean containsKey(Object key):是否包含指定的key
 *      boolean containsValue(Object value):是否包含指定的value
 *      int size():返回map中key-value对的个数
 *      boolean isEmpty():判断当前map是否为空
 *      boolean equals(Object obj):判断当前map和参数对象obj是否相等
 *      元视图操作的方法:
 *      Set keySet():返回所有key构成的Set集合
 *      Collection values():返回所有value构成的Collection集合
 *      Set entrySet():返回所有key-value对构成的Set集合
 *
 */
public class MapTest {

    /**
     *  元素查询的操作:
     *  Object get(Object key):获取指定key对应的value
     *  boolean containsKey(Object key):是否包含指定的key
     *  boolean containsValue(Object value):是否包含指定的value
     *  int size():返回map中key-value对的个数
     *  boolean isEmpty():判断当前map是否为空
     *  boolean equals(Object obj):判断当前map和参数对象obj是否相等
     */
    @Test
    public void test4(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put(45,123);
        map.put("BB",56);
        // Object get(Object key)
        System.out.println(map.get(45));
        //containsKey(Object key)
        boolean isExist = map.containsKey("BB");
        System.out.println(isExist);

        isExist = map.containsValue(123);
        System.out.println(isExist);

        map.clear();

        System.out.println(map.isEmpty());
    }

    /**
     * 添加、删除、修改操作:
     *  Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
     *  void putAll(Map m):将m中的所有key-value对存放到当前map中
     *  Object remove(Object key):移除指定key的key-value对,并返回value
     *  void clear():清空当前map中的所有数据
     */
    @Test
    public void test3(){
        Map map = new HashMap();
        //添加
        map.put("AA",123);
        map.put(45,123);
        map.put("BB",56);
        //修改
        map.put("AA",87);

        System.out.println(map);

        Map map1 = new HashMap();
        map1.put("CC",123);
        map1.put("DD",456);
        map.putAll(map1);

        System.out.println(map);

        //remove(Object key)
        Object value = map.remove("CC");
        System.out.println(value);
        System.out.println(map);

        //clear()
        map.clear();//与map = null操作不同
        System.out.println(map.size());
        System.out.println(map);
    }
}
import org.junit.Test;

import java.util.*;
/**
 *  五、Map中定义的方法:
 *      添加、删除、修改操作:
 *      Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
 *      void putAll(Map m):将m中的所有key-value对存放到当前map中
 *      Object remove(Object key):移除指定key的key-value对,并返回value
 *      void clear():清空当前map中的所有数据
 *      元素查询的操作:
 *      Object get(Object key):获取指定key对应的value
 *      boolean containsKey(Object key):是否包含指定的key
 *      boolean containsValue(Object value):是否包含指定的value
 *      int size():返回map中key-value对的个数
 *      boolean isEmpty():判断当前map是否为空
 *      boolean equals(Object obj):判断当前map和参数对象obj是否相等
 *      元视图操作的方法:
 *      Set keySet():返回所有key构成的Set集合
 *      Collection values():返回所有value构成的Collection集合
 *      Set entrySet():返回所有key-value对构成的Set集合
 *
 * 总结:常用方法:
 *    添加:put(Object key,Object value)
 *    删除:remove(Object key)
 *    修改:put(Object key,Object value)
 *    查询:get(Object key)
 *    长度:size()
 *    遍历:keySet() / values() / entrySet()
 *
 *  面试题:
 *  1. HashMap的底层实现原理?
 *  2. HashMap 和 Hashtable的异同?
 *      1.HashMap与Hashtable都实现了Map接口。由于HashMap的非线程安全性,效率上可能高于Hashtable。Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
 *      2.HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
 *      3.HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
 *      4.Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
 *      5.Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
 *
 *  3. CurrentHashMap 与 Hashtable的异同?(暂时不讲)
 *
 */
public class MapTest {

    /**
     *  元视图操作的方法:
     *  Set keySet():返回所有key构成的Set集合
     *  Collection values():返回所有value构成的Collection集合
     *  Set entrySet():返回所有key-value对构成的Set集合
     */
    @Test
    public void test5(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put(45,1234);
        map.put("BB",56);

        //遍历所有的key集:keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("*****************");

        //遍历所有的values集:values()
        Collection values = map.values();
        for(Object obj : values){
            System.out.println(obj);
        }
        System.out.println("***************");
        //遍历所有的key-values
        //方式一:
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            //entrySet集合中的元素都是entry
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "---->" + entry.getValue());

        }
        System.out.println("/");

        //方式二:
        Set keySet = map.keySet();
        Iterator iterator2 = keySet.iterator();
        while(iterator2.hasNext()){
            Object key = iterator2.next();
            Object value = map.get(key);
            System.out.println(key + "=====" + value);
        }
    }
}

Map中key、value和key-value的遍历实现

@Test
    public void test1(){
        Map<String, Integer> map = new HashMap<>();
        map.put("AA",256);
        //遍历key
        Set<String> keySet = map.keySet();
        for (String key: keySet){
            System.out.println(key);
        }
        //遍历value
        Collection<Integer> values = map.values();
        Iterator<Integer> iterator = values.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //遍历key-value
        Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Map.Entry<String,Integer> entry = iterator1.next();
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + "--->" + value);
        }
    }

1、HashMap(Map接口使用频率最高的实现类)

特点:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value

HashMap的底层:数组+链表(jdk7及之前)
                              数组+链表+红黑树(jdk 8)

 1.1HashMap在jdk7中实现原理

HashMap map=new HashMap():
*        在实例化以后,底层创建了长度是16的一维数组Entry[]  table。
*        ...可能已经执行过多次put...
        map. put(key1,value1):
        首先,该用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
*        如果此位置上的数据为空、此时的kev1-value1添加成功。---情况1
*        (如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
                                如果key 1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。----情况2

                                如果key1的哈希值和已经存在的某一个数据(key2−vaLue2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,比较:
*                                如果equals()返回false:此时key1-value1添加成功。----情况3
*                                如果equals()返回true:使用value1替换value2。
*
*        补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。
*        在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原来的数据复制过来。

1.2HashMap在jdk8中相较于jdk7在底层实现方面的不同

1. new HashMap():底层没创建一个长度为16的数组
2. jdk 8底层的数组是:Node[],而非Entry[]
3.首次调用put()方法时,底层创建长度为16的数组
4.jdk7底层结构只:数组+链表。jdk8中底层结构:数组+链表+红黑树。
        4.1形成链表时,七上八下(jdk7:新的元素指向旧的元素。jdk8:旧的元素指向新的元素)
        4.2当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,此时此索引位置上的所有数据改为使用红黑树存储。

1.3 HashMap底层典型属性的属性说明

DEFAULT_INITIAL_CAPACITY:HashMap的默认容量,16
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:θ. 75,
threshold:扩容的临界值,=容量*填充因子:16*0.75=>12
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64

2、LinkedHashMap

特点:保证在遍历map元素时,可以按照添加的顺序实现遍历。
原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
        对于频繁的遍历操作,此类执行效率高于HashMap。

LinkedHashMap是HashMap的子类

在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序

与LinkedHashSet类似,LinkedHashMap可以维护Map 的迭代顺序:迭代顺序与Key-Value 对的插入顺序一致

HashMap中的内部类:Node

LinkedHashMap中的内部类:Entry

2.1LinkedHashMap的底层实现原理(了解)

LinkedHashMap底层使用的结构与HashMap相同,因为LinkedHashMap继承于HashMap.

区别就在于:LinkedHashMap内部提供了Entry,替换HashMap中的Node.

3、TreeMap

特点:保证按照添加的key-value.对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
底层使用红黑树

4、Hashtable(古老实现类)

特点:作为古老的实现类;线程安全的,效率低;不能存储null的key和value

5、Properties

特点:常用来处理配置文件。key和value都是String类型"

五、工具类Collections

作用

操作Collection和Map的工具类

Collections常用方法

查找、替换

查找、替换
●object max( Collection ):根据元素的自然顺序,返回给定集合中的最大元素

●Object max( Collection , Comparator ):根据 Comparator 指定的顺序,返回给定集合中的最大元素
●Object min( Collection )
●Object min( Collection ,  Comparator )
● int  frequency ( Collection , Object):返回指定集合中指定元素的出现次数
●void  copy(List dest, List src):将src中的内容复制到dest中
● boolean  replaceAll(List list,Object oldVal, Object  newVal ):使用新值替换List对象的所有旧值

排序操作:(均为static方法)
●reverse(List):反转List中元素的顺序
●shuffle(List);对List集合元素进行随机排序
●sort(List):根据元素的自然顺序对指定List集合元素按升序排序
●sort(List, Comparator ):根据指定的 Comparator 产生的顺序对List集合元素进行排序
●swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换Ⅰ

说明:ArrayList和HashMap都是线程不安全的,如果程序要求线程安全,我们可以将ArrayList、 HashMap转换为线程安全的。

使用synchronizedList(List list)和synchronizedMap(Map map)


 面试题

1. Map存储数据的特点是什么?并指明key,value,entry存储数据的特点。
2.描述HashMap的底层实现原理(idk8版)-
3. Map中常用实现类有哪些?各自有什么特点?
4.如何遍历Map中的key-value对,代码实现。
5.  Collection 和 Collections 的区别?


最后

 附上我的学习视频:尚硅谷Java入门视频教程(在线答疑+Java面试真题)

 本文只是博主的一点点Java学习笔记,往后可能会继续更新,谢谢大家的浏览支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

板牙叮咚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值