Java Day15

Java

day15——2023.8.25

Map

之前的Collection称为集合,使用它可以存放单个的对象,可以快速找到我们想要的元素。

而Map称为映射,它可以存放一对键值数据,一对key:value数据

比如:name:张三,age:20,1001:Student{张三,20,1班}
在这里插入图片描述

Map和Collection的区别

1,Map中的元素,是成对出现的,Map中的键是唯一的,值是可以重复的,可以有null值

2,Collection中的元素,都是单个出现的,Collection的子类,set中元素是唯一的,不能重复,List是可以重复的

Map的功能
1.添加功能

V put(K key , V value)

将指定的值与该映射中的指定键相关联(可选操作)。

2.获取功能

V get(Object key)

返回到指定键所映射的值,或 null如果此映射包含该键的映射。

Set<Map.Entry<K,V>> entrySet()

返回此Map中包含的映射的Set视图。

Set keySet()

返回此Map中包含的键的Set视图。

Collection values()

返回此地图中包含的值的Collection视图

3.判断功能

boolean isEmpty()

如果此Map不包含键值映射,则返回 true 。

boolean containsKey(Object key)

如果此映射包含指定键的映射,则返回 true 。

boolean containsValue(Object value)

如果此地图将一个或多个键映射到指定的值,则返回 true 。

4.删除功能

V remove(Object key)

如果存在(从可选的操作),从该地图中删除一个键的映射。

void clear()

从该地图中删除所有的映射(可选操作)。

5.长度功能

int size()

返回此地图中键值映射的数量。

Map的常用子类 HashMap

在这里插入图片描述
HashMap基于哈希表的实现的Map接口。

此实现提供了所有可选的Map操作,并允许null的值和null键,null键不能重复。线程不安全的,存放数据是无序的

构造方法

HashMap()

构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。

HashMap(int initialCapacity)

构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。

HashMap(int initialCapacity, float loadFactor)

构造一个空的 HashMap具有指定的初始容量和负载因子

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap() ; //键值都是String
        //通过put方法,完成map数据的存放
            map.put("one","hello");
            map.put("one","mysql");
            map.put("two","java");
            map.put("three","world");
            map.put("1","oracle");
            map.put(null,"spring"); //可以把null作为键
            map.put(null,"Linux"); //可以把null作为键,相同的键对应的值被覆盖
        System.out.println(map);
        //获取
        System.out.println(map.get("one"));
        System.out.println(map.get("2"));  //获取不存在,返回null
        //判断
        System.out.println(map.containsKey("one")); //true
        System.out.println(map.containsValue("hello"));//false
        //移除
        map.remove("one");
        System.out.println(map);
        //长度
        System.out.println(map.size());
        System.out.println("------------------------");
        //遍历
        //第一种:先获取key,通过key再获取值
        Set<String> set = map.keySet(); //先获取所有key的set集合
        for (String key : set) {
            //遍历set
            System.out.println(key + "----" + map.get(key));
        }

        System.out.println("------------------------");
        Map<Integer, String> map1 = new HashMap() ;//键是Integer,值是String
            map1.put(1,"hello");
            map1.put(2,"java");
            map1.put(3,"oracle");
        System.out.println(map1);

        //分开分别获取key和value
        for (Integer key : map1.keySet()) {
            System.out.println("key:" + key);
        }
        for (String value : map1.values()) {
            System.out.println("value:" + value);
        }
        System.out.println("------------------------");


        Map<String, Object> map2 = new HashMap() ;//键是String,值是对象
            map2.put("name","张三");
            map2.put("age",20);
            map2.put("1001",new Student("李四",22,"1班"));
        System.out.println(map2);

        //使用entrySet()方法来实现遍历
        Set<Map.Entry<String, Object>> entries = map2.entrySet();
        //使用增强for遍历返回的entrySet
        for (Map.Entry<String, Object> entry : entries) {
            System.out.println(entry.getKey() + "--" + entry.getValue());
        }
        System.out.println("------------------------");
        //使用iterator遍历返回的entrySet
        Iterator<Map.Entry<String, Object>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Object> entry = iterator.next();
            System.out.println(entry.getKey() + "--" + entry.getValue());
        }
    }
}

HashMap的源码解析

HashMap的底层结构 :jdk1.7 数组+链表 ,jdk1.8 之后 数组+链表+红黑树

数组和链表都可以按照用户的意愿来排列元素的次序,是有序(存取有序),

链表中也有缺点,想要获取某个元素,要访问所有元素,直到找到位置,这是比较耗时的

数组+链表的组合,可以看做是一个新的数据结构:散列表 (hash表)

这个结构在存储的时候,不在意元素的顺序,也能够快速的找到元素。

散列表的原理

将每个对象 计算出一个 数值,这个数值称为散列码(hash码),根据这些散列吗,计算数据保存的位置。

每个散列表,在Java中,也称之为 桶 。

一个桶上,多个对象存储的时候可能会遇到散列码相同的情况,这个是,散列码相同的对象,就得存储到同一个位置上。这种情况称为 :散列冲突(hash冲突)

发生散列冲突后,就需要将存放的数据,进行比较,看看发生冲突的对象是否是同一个对象,如果是同一个对象,将原来的替换,如果不是,将对象添加在桶的链表上

HashMap的基本说明

注释上的说明:

基于哈希表的实现的Map接口,允许null的值和null键,不能保证Map的顺序

HashMap的对象有两个影响其性能的参数,初始容量16和负载因子0.75

初始容量太高和负载因子太低,都是不太好的,会影响性能

当存储的数量达到了16*0.75=12的时候,哈希表开始扩容,扩容2倍

如果要存储很多数据在Map中,可以在初始化的时候,把容量设置的高一些,可以提升效率

HashMap是线程不安全的

属性的说明:

默认的初始容量值是16,必须是2的n次方

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

最高容量是2的30次方

static final int MAXIMUM_CAPACITY = 1 << 30;

默认的负载因子是0.75f

static final float DEFAULT_LOAD_FACTOR = 0.75f;

内部链表结构转成红黑树结构的节点,链表的数量=8个

static final int TREEIFY_THRESHOLD = 8;

当树的结构中数量=6了,退化为链表

static final int UNTREEIFY_THRESHOLD = 6;

链表结构转为红黑树另一个要满足的条件,桶的数量=64

static final int MIN_TREEIFY_CAPACITY = 64;

构造方法
无参构造

public HashMap() {

​ this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
​ }

有参构造

public HashMap(int initialCapacity) {

​ this(initialCapacity, DEFAULT_LOAD_FACTOR);

​ }

public HashMap(int initialCapacity, float loadFactor) {

​ //如果初始值、加载因子小于0或者是非数字,就抛异常

//如果初始值超过了最大范围,就把初始值设为最大值

​ this.loadFactor = loadFactor;

​ this.threshold = tableSizeFor(initialCapacity);

​ }

tableSizeFor(initialCapacity) 用来将传入的数值转成2的n次方后,返回

《HashMap中内容解析》

普通方法
put方法:

1,将key和value传入put方法后,先把key传入hash方法后,完成计算,在传入putVal这个方法

public V put(K key, V value) {

​ return putVal(hash(key), key, value, false, true);

​ }

2,key传入hash方法后,将key的hashCode值,和key的hashCode值右移16位后,做的位异或运算

这种计算方式是为了减少hash冲突。

static final int hash(Object key) {

​ int h;

​ return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

​ }

3,将key经过hash计算后的值、key本身的值、value值,传入putVal

这个是putVal方法中的一个代码片段,表示存放元素的时候,将数组(hashmap对象)的长度-1之后,和key计算出来的hash值做运算,通过运算结果判断这个数组的下标位置是否存在元素,如果没有元素,就将元素传入新节点,创建后,放到这个数组的下标位置

if ((p = tab[i = (n - 1) & hash]) == null)

​ tab[i] = newNode(hash, key, value, null);

代码拆分:

i = (n - 1) & hash; //计算出来数组的下标

p = tab[i]; //通过下标取出来的值

if(p == null){ //如果这个数组的下标元素为null,那么将这个下标位置指定元素

tab[i] = newNode(hash, key, value, null);

}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

​ boolean evict) {

​ Node<K,V>[] tab; Node<K,V> p; int n, i;

​ if ((tab = table) == null || (n = tab.length) == 0)

​ n = (tab = resize()).length;

​ if ((p = tab[i = (n - 1) & hash]) == null)

​ tab[i] = newNode(hash, key, value, null);

​ else {

​ Node<K,V> e; K k;

​ if (p.hash == hash &&

​ ((k = p.key) == key || (key != null && key.equals(k))))

​ e = p;

​ else if (p instanceof TreeNode)

​ e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);

​ else {

​ for (int binCount = 0; ; ++binCount) {

​ if ((e = p.next) == null) {

​ p.next = newNode(hash, key, value, null);

​ if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st

​ treeifyBin(tab, hash);

​ break;

​ }

​ if (e.hash == hash &&

​ ((k = e.key) == key || (key != null && key.equals(k))))

​ break;

​ p = e;

​ }

​ }

​ if (e != null) { // existing mapping for key

​ V oldValue = e.value;

​ if (!onlyIfAbsent || oldValue == null)

​ e.value = value;

​ afterNodeAccess(e);

​ return oldValue;

​ }

​ }

​ ++modCount;

​ if (++size > threshold)

​ resize();

​ afterNodeInsertion(evict);

​ return null;

​ }

HashMap中怎么使用散列表存放元素

1,先判断键值对数组table[i]是否为null或者为空,如果是空,执行reisze()方法进行扩容

2, 根据键值key计算hash值,得到插入的数组索引位置 i,如果table[i] == null,直接创建节点,插入到数组下标i位置 ,然后计算是否需要扩容,如果table[i] 不为空,就继续下一步

3,判断table[i] 的首个元素是否和key一样,如果相同(通过hashCode值和equals判断),直接把value覆盖,如果不同,继续下一步

4,判断table[i] 是否是一颗红黑树,如果是红黑树,直接在树上插入键值对数据,否则继续下一步

5,遍历table[i],判断元素的next节点是否为null,如果是null,就把新的节点放入链表中,并让上一个节点的next,指向新节点,接着判断链表的长度是否大于8,如果大于8,把链表转为红黑树

6,插入成功,判断实际的size值是否超过了 扩容的阈值,如果超过,则进行扩容

HashMap中,如何扩容?

通过resize()方法完成扩容

final Node<K,V>[] resize() {

​ Node<K,V>[] oldTab = table;

​ int oldCap = (oldTab == null) ? 0 : oldTab.length;

​ int oldThr = threshold;

​ int newCap, newThr = 0;

​ if (oldCap > 0) {

​ if (oldCap >= MAXIMUM_CAPACITY) {

​ threshold = Integer.MAX_VALUE;

​ return oldTab;

​ }

​ else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&

​ oldCap >= DEFAULT_INITIAL_CAPACITY)

​ newThr = oldThr << 1; // double threshold

​ }

​ else if (oldThr > 0) // initial capacity was placed in threshold

​ newCap = oldThr;

​ else { // zero initial threshold signifies using defaults

​ newCap = DEFAULT_INITIAL_CAPACITY;

​ newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);

​ }

​ if (newThr == 0) {

​ float ft = (float)newCap * loadFactor;

​ newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?

​ (int)ft : Integer.MAX_VALUE);

​ }

​ threshold = newThr;

​ @SuppressWarnings({“rawtypes”,“unchecked”})

​ Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];

​ table = newTab;

​ if (oldTab != null) {

​ for (int j = 0; j < oldCap; ++j) {

​ Node<K,V> e;

​ if ((e = oldTab[j]) != null) {

​ oldTab[j] = null;

​ if (e.next == null)

​ newTab[e.hash & (newCap - 1)] = e;

​ else if (e instanceof TreeNode)

​ ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);

​ else { // preserve order

​ Node<K,V> loHead = null, loTail = null;

​ Node<K,V> hiHead = null, hiTail = null;

​ Node<K,V> next;

​ do {

​ next = e.next;

​ if ((e.hash & oldCap) == 0) {

​ if (loTail == null)

​ loHead = e;

​ else

​ loTail.next = e;

​ loTail = e;

​ }

​ else {

​ if (hiTail == null)

​ hiHead = e;

​ else

​ hiTail.next = e;

​ hiTail = e;

​ }

​ } while ((e = next) != null);

​ if (loTail != null) {

​ loTail.next = null;

​ newTab[j] = loHead;

​ }

​ if (hiTail != null) {

​ hiTail.next = null;

​ newTab[j + oldCap] = hiHead;

​ }

​ }

​ }

​ }

​ }

​ return newTab;

​ }

get方法步骤

先计算key的hash值,调用getNode()方法获取到对应的value

getNode() :先计算hash是否在hash表上,如果在桶的首位能找到,直接返回,否则看看是否是红黑树,如果是,就在树中找,不是就遍历链表

remove()方法

通过计算key的hash值删除value

具体通过removeNode()方法实现:

判断桶是否为空,映射的哈希值是否存在,如果在桶的首位找到对应的元素,记录下来,

不在首位就去红黑树或者链表中 去找到,找到对应的节点了,将内容删除

Map.Entry对象

Map中没有迭代器对象,所以Map的遍历只能通过将键值返回到集合中的方式,完成遍历

第一种遍历方式,通过Map子代的keySet()方法和values()方法

keySet()方法用来返回所有的key的set集合,可以用来获取到所有的key

values()方法,用来返回所有的value的集合,然后可以用来获取所有的value

第二种遍历方式,通过Map中的entrySet()方法

Set<Map.Entry<K,V>> entrySet()

这个方法方法,map对象调用后,也是返回一个set集合,但是这个set集合中,存放的是Map.Entry对象

Map.Entry是Map接口的内部接口,里面提供了getKey()和getValue()两个抽象方法,既然存在这两个方法,那么返回的set集合中的每个Entry对象,都可以通过这两个方法,获取键和值

通过查看源码发现,HashMap中的 内部类 Node,实现了Map.Entry接口

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

这个Node实际上又是存放HashMap中键值数据的节点,所以说,其实每个Map.Entry对象就是一对键值数据的存放对象(通过它的自实现类Node来实现数据存放)

那既然实现了Map.Entry接口,Node类必然实现了接口中的方法,getKey()和getValue()方法

因为key和value 是Node类的属性,所以,直接以getter方法的形式返回属性值就可以了。

public final K getKey() { return key; }

​ public final V getValue() { return value; }

HashMap和HashTable的区别

从存储结构来讲,HashTable除了没有红黑树,其他结构一样,HashTable扩容 是 2n+1,它和HashMap最大的不同是,HashTable是线程安全的,不允许key和value为null,HashTable是一个过时的集合了,所以将来如果需要使用线程安全的HashMap,一般使用ConcurrentHashMap

HashMap总结

1,JDK8中,HashMap底层结构是 :数组+单向链表 + 红黑树, 无序、可以存放null值,null键,键不能重复

2,HashMap的初始容量是16,负载因子默认是0.75,当容量达到16*0.75=12的时候,会扩容

3,初始容量和负载因子都可以自己设置 ,负载因子设置的过大和过小都不太好,

过大的话,会减少扩容,增加哈希冲突,

过小可以减少冲突,扩容次数变多

4,如果需要存入大量元素,那么可以指定一个特定的初始容量,HashMap的容量值都是2的n次方

5,当散列表中链表的数量超过8,并且散列表的容量超过了64,链表会进行转树的操作

LinkedHashMap
继承结构

在这里插入图片描述

注释说明

1,底层是 散列表(数组+链表) + 双向链表

2,允许为null,线程不安全

3,插入顺序有序的

4,负载因子和初始容量影响LinkedHashMap的性能

构造方法

LinkedHashMap()

构造具有默认初始容量(16)和负载因子(0.75)的空插入创建 LinkedHashMap实例。

LinkedHashMap(int initialCapacity)

构造具有指定初始容量和默认负载因子(0.75)的空插入创建 LinkedHashMap实例。

LinkedHashMap(int initialCapacity, float loadFactor)

构造具有指定初始容量和负载因子的空插入创建 LinkedHashMap实例。

LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)

accessOrder - 创建模式 - true的访问顺序, false的插入顺序

构造一个空的 LinkedHashMap实例,具有指定的初始容量,负载因子和创建模式。


public class HashMapDemo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
        //添加元素
        linkedHashMap.put("one","hello");
        linkedHashMap.put("two","world");
        linkedHashMap.put("three","java");
        linkedHashMap.put("four","oracle");
        //获取
        System.out.println(linkedHashMap.get("two"));
        //判断
        System.out.println(linkedHashMap.containsKey("one"));
        System.out.println(linkedHashMap.containsValue("hello"));
        //移除
        linkedHashMap.remove("two");
        System.out.println(linkedHashMap);
        //遍历
        Set<String> set = linkedHashMap.keySet();
        for (String key : set) {

            System.out.println(key + " -- " + linkedHashMap.get(key));
        }
        //通过entrySet完成遍历
        

    }
}

accessOrder - 创建模式 - true的访问顺序, false的插入顺序

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        //accessOrder - 创建模式 - true的访问顺序, false的插入顺序
        LinkedHashMap<Integer, String> map =
                new LinkedHashMap(16,0.75f,true);

        int i = 1;
        map.put(i++,"hello1");
        map.put(i++,"hello2");
        map.put(i++,"hello3");
        map.put(i++,"hello4");
        map.put(i++,"hello5");

        //访问之后,元素的顺序被改变
        System.out.println(map.get(3));
        System.out.println(map.get(1));

        //Set<Integer> sets = map.keySet();
        //for (Integer key : sets) {
        //    System.out.println(key + "--" + map.get(key)) ;
        //}
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        for (Map.Entry<Integer, String> entry : entries) {
            System.out.println(entry.getKey() + "--" + entry.getValue());
        }
    }
}
LinkedHashMap总结

LinkedHashMap是HashMap的子类,LinkedHashMap比HashMap多了一个双向链表的结构

LinkedHashMap大部分方法都是来自HashMap

它们之间很多的地方都体现了多态的使用

LinkedHashMap可以设置两种遍历顺序:

访问顺序 和 插入顺序,默认是插入顺序的

TreeMap

在这里插入图片描述

注释说明

TreeMap实现了NavigableMap接口,NavigableMap继承了SortedMap,使用TreeMap有序

TreeMap的层是红黑树

线程不同步的

使用Comparator或者Comparable实现键的比较,完成最终数据的排序

构造方法

TreeMap()

使用其键的自然排序构造一个新的空树状图。

TreeMap(Comparator<? super K> comparator)

构造一个新的,空的树图,按照给定的比较器排序。

TreeMap(Map<? extends K,? extends V> m)

构造一个新的树状图,其中包含与给定地图相同的映射,根据其键的 自然顺序进行排序 。

TreeMap(SortedMap<K,? extends V> m)

构造一个包含相同映射并使用与指定排序映射相同顺序的新树映射。

public class TreeMapDemo {
    public static void main(String[] args) {
        //用无参构造创建的TreeMap,默认使用自然排序
        TreeMap<String, String> map = new TreeMap<>();
        //添加元素
        map.put("1","hello");
        map.put("2","java");
        map.put("4","world");
        map.put("5","spring");
        map.put("3","list");

        System.out.println(map);


        //构造TreeMap对象的时候,键必须要可以互相比较
        //如果传入键的时候键的数据类型不一致,可能会导致异常的发生
        TreeMap<Object, String> map1 = new TreeMap<>();
        //map1.put(1,"hello");
        //map1.put("a","java");
        //map1.put(new Student(),"oracle");
        //System.out.println(map1);

        //使用对象作为键,作为键的对象,必须要实现Comparable(比较器)接口
        //重写其中的CompareTo()方法
        TreeMap<Student, String> map2 = new TreeMap<>();
        map2.put(new Student("jack",20,"1班"),"hello");
        map2.put(new Student("lucy",22,"1班"),"oracle");
        map2.put(new Student("zs",22,"2班"),"java");
        map2.put(new Student("lisi",24,"2班"),"mysql");
        map2.put(new Student("wangwu",21,"2班"),"spring");
        System.out.println(map2);
    }
}


public class Student implements Comparable<Student> {
    private String name;
    private int age;
    private String className;

    public Student() {
    }

    public Student(String name, int age, String className) {
        this.name = name;
        this.age = age;
        this.className = className;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return className != null ? className.equals(student.className) : student.className == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        result = 31 * result + (className != null ? className.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", className='" + className + '\'' +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        if (o.age> this.age){
            return -1;
        }
        if (o.age < this.age){
            return 1;
        }
        if (o.name.compareTo(this.name) > 0){
            return -1;
        }
        if (o.name.compareTo(this.name) < 0){
            return 1;
        }


        if (o.className.compareTo(this.className) > 0){
            return -1;
        }
        if (o.className.compareTo(this.className) < 0){
            return 1;
        }
        return 0;
    }

}

构造TreeMap对象的时候,传入Comparator对象

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


public class TreeMapDemo01 {
    public static void main(String[] args) {
        TreeMap<User, String> treeMap =
                new TreeMap<>(new Comparator<User>() {
                    @Override
                    public int compare(User o1, User o2) {
                        if (o1.getAge() > o2.getAge()){
                            return 1;
                        }
                        if (o1.getAge() < o2.getAge()){
                            return -1;
                        }
                        if (o1.getName().compareTo(o2.getName()) > 0){
                            return 1;
                        }
                        if (o1.getName().compareTo(o2.getName()) < 0){
                            return -1;
                        }
                        return 0;
                    }
                });

        treeMap.put(new User("jack",20),"java");
        treeMap.put(new User("tom",22),"hello");
        treeMap.put(new User("tony",19),"hello");
        treeMap.put(new User("lucy",22),"hello");

        System.out.println(treeMap);
    }
}
TreeMap的总结

1.底层是红黑树,能够实现该Map集合有序(自然排序)
2.key不能为null
3.可以在构造方法中传入Comparator对象,实现比较方法,也可以让键对象实现Comparator接口,并重写compareTo()方法来实现 键的自然排序
4.TreeMap也是线程不安全的

1,常见的数据结构及特点

栈:先进后出
队列:先进先出
数组:查询速度快,增删速度慢
链表:查询速度慢,增删速度快
树:每个节点有0个或多个子节点;没有父节点的节点叫做根节点;每一个非父节点,有且仅有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树;增删查询都很快

2,Collection的体系结构

列表(List)
集(Set)
映射(Map)
栈(Stack)
队列(Queue)
在这里插入图片描述

3,List集合的特点,Map的特点

List接口是Collection接口的子接口,表示有序的序列,可以通过索引访问到List中的元素
List中可以存放 重复的元素 ,并且可以存放null,存放多个null
List接口中提供了 ListIterator,除了实现Iterator接口中的往后遍历的方法,还写了往前遍历的方法
Map一次存储两个元素,一个是key(键),一个是value(值)
Map中的key(键)是唯一的,
Map中的value(值)是可以重复的,可以有null值

4,ArrayList的特点

可变数组实现List接口,相当于一个动态数组实现所有方法
可以存放任意类型的元素,包括null
创建ArrayList会有一个容量,来定义将来存放元素的数组的大小

5,HashMap的特点

键值对存储
快速查询
无序存储
不允许键重复
允许存放空键和空值
非线程安全
容量可调
迭代顺序不确定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值