当前位置: 首页 > 图灵资讯 > 技术篇> Java类集框架详细汇总

Java类集框架详细汇总

来源:图灵教育
时间:2023-05-31 09:21:24

Java类集框架详细汇总_hashtable

前言:

Java的类集框架很多,也很重要。这里给出的图解可以理解为相应的继承关系,也可以作为重要知识点回顾;

Java类集框架详细汇总_redis_02

Collection集合接口

继承自:Iterable

public interface Collection<E> extends Iterable<E>

java.util.Collection是单值集合操作的最大父接口,其中有几种核心操作方法和常用操作方法;

Modifier and Type

Method(public)

Description

boolean

add(E e)

确保该集合包含指定元素(可选操作)。

boolean

addAll(Collection<? extends E> c)

在此集中添加指定集合中的所有元素(可选操作)。

void

clear()

从集合中删除所有元素(可选操作)。

boolean

contains(Object o)

如果该集包含指定元素,则返回true。

boolean

remove(Object o)

若存在,则集中删除指定元素的单个实例(可选操作)。

int

size()

回到这个集合中的元素数。

Object[]

toArray()

返回包含此集中所有元素的数组。

Iterator<E>

iterator()

返回迭代器,以迭代集合中的元素。

上述方法有两种特殊的方法cotainsremove;都需要equals只有支持方法,才能删除和查询数据;否则,元素就找不到了。

后面是衍生的子类方法。

List集合

最大特点:允许保存重复元素,并在父亲界面上扩展其他方法;

继承关系:

public interface List<E> extends Collection<E>

Modifier and Type

Method(public)

Description

void

add(int index, E element)

Inserts the specified element at the specified position in this list (optional operation).

boolean

add(E e)

Appends the specified element to the end of this list (optional operation).

ListIterator<E>

listIterator()

Returns a list iterator over the elements in this list (in proper sequence).

static <E> List<E>

of()

Returns an unmodifiable list containing zero elements.

default void

forEach(Consumer<? super T> action)

Performs the given action for each element of theIterableuntil all elements have been processed or the action throws an exception.

实例:

package Java从入门到项目实战.Java类集框架.List集合;import java.util.List;public class 多数据保存 {    public static void main(String[] args) {        List<String> all = List.of("xbhg","Hello","World","welcome");        Object[] result = all.toArray();        for (Object t: result) {            System.out.println(t);        }        System.out.println("-分割线-";        all.forEach(System.out::println); ///方法引用部分引用结构方法    }}

ArrayList子类

继承结构如下:

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

实例化:允许重复元素按添加时的顺序保存和保存;

package Java从入门到项目实战.Java类集框架.List集合;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class ArrayList实例List {    public static void main(String[] args) {        List<String> all = new ArrayList<String>();        all.add("Hello");        all.add(“你好”);        all.add(“你好”);        all.add("xbhog");        System.out.println(all);        all.forEach(System.out::print);        //lambda表达式        all.forEach((str)->{            System.out.print(str+"、");        });    }}

集合操作方法:

package Java从入门到项目实战.Java类集框架.List集合;import java.util.ArrayList;import java.util.List;public class ArrayLIST集相关操作 {    public static void main(String[] args) {        List<String> all = new ArrayList<String>();        System.out.println("集合是空的吗?"+all.isEmpty()+"、“集合元素数”+all.size());        all.add("1");        all.add("2");        all.add("3");        System.out.println("集合是空的吗?"+all.isEmpty()+"、“集合元素数”+all.size());        System.out.println(all.get(1));        System.out.println(all.remove("3"));        System.out.println("集合是空的吗?"+all.isEmpty()+"、“集合元素数”+all.size());    }}

ArrayList原理分析:重点:

首先要明确ArrayList是通过数组实现的;这就导致了ArrayList通过什么方式进行扩容操作,以及在什么情况下才会扩容?

ArrayList类中的数组是在结构方法中开辟的空间;相应的参与和参与结构方法:

无参与结构方法:使用空数组(长度为0)初始化,第一次使用时为其开辟空间(初始化程度为10);

public ArrayList() {    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}////默认开放空间大小privatete static final int DEFAULT_CAPACITY = 10;/**     * Shared empty array instance used for empty instances.     */private static final Object[] EMPTY_ELEMENTDATA = {};/**     * Shared empty array instance used for default sized empty instances. We     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when     * first element is added.     */private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

有参结构方法:如果长度大于0,则以指定长度打开数组空间;如果长度为0,则按无参结构方法进行;如果是负数,则抛出ILLegalargumentexception异常;

public ArrayList(Collection<? extends E> c) {    elementData = c.toArray();    if ((size = elementData.length) != 0) {        // defend against c.toArray (incorrectly) not returning Object[]        // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)        if (elementData.getClass() != Object[].class)            elementData = Arrays.copyOf(elementData, size, Object[].class);    } else {        // replace with empty array.        this.elementData = EMPTY_ELEMENTDATA;    }}

当数组扩展时,以数组复制的形式将旧数组中的数据复制到开放的新数组中;

最大程度如下:

/**     * The maximum size of array to allocate (unless necessary).     * Some VMs reserve some header words in an array.     * Attempts to allocate larger arrays may result in     * OutOfMemoryError: Requested array size exceeds VM limit     */private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

ArrrayList保存自定义对象:

该操作必须包括相关的添加、删除和更改;由于实现contains和remove方法需要通过对象比较来完成;因此,我们需要复制equals方法

package Java从入门到项目实战.Java类集框架.List集合;import java.util.ArrayList;import java.util.List;class Person{    private String name;    private int age;    public Person(String name,int age){        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    public void setName(String name) {        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    public boolean equals(Object obj){        if(this== obj) return true;        if(obj == null) return false;        if(!(obj instanceof Person)) return false;        Person pe = (Person) obj;        return this.name.equals(pe.name) && this.age == pe.age;    }    @Override    public String toString() {        return "姓名:"+this.name +"、年龄:"+this.age;    }}public class ArrayList保存自定义对象 {    public static void main(String[] args) {        List<Person> std = new ArrayList<Person>();        std.add(new Person("xbhog",1));        std.add(new Person(小明),2);        std.add(new Person(“小白”,3));        System.out.println(-删除前的数据内容-”);        std.forEach((person)->{            System.out.println(姓名:"+person.getName()+"、年龄:"+person.getAge());        });        System.out.println(-删除后的数据内容-");        std.remove(new Person(“小白”,3));        std.forEach((person)->{            System.out.println(姓名:"+person.getName()+"、年龄:"+person.getAge());        });        System.out.println("-查看数据是否存在-";        System.out.println(std.contains(new Person(“小明”,2)));    }}

LinkedList子类:

继承结构如下:基于链表形式的实现

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable

实现LinkedList的集合操作:

package Java从入门到项目实战.Java类集框架.List集合;import java.util.LinkedList;import java.util.List;public class LinkList链表操作 {    public static void main(String[] args) {        List<String> all = new LinkedList<String>();        all.add("java");        all.add("python");        all.add("Linux");        System.out.println(all);        System.out.println(all.get(2));        System.out.println(all.get(1));    }}

Vector子类:

继承结构如下:

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

从继承结构上可以看出,Vector子类的使用方式与ArrayList相同;

package Java从入门到项目实战.Java类集框架.List集合;import java.util.List;import java.util.Vector;public class Vector子类实现List接口 {    public static void main(String[] args) {        List<String> all = new Vector<String>();        all.add("asda");        all.add(“你好”);        all.add("buhao");        System.out.println(all);    }}

不同点:

以下是vector操作方法,采用synchronizeded 同步处理;属于线程安全,但效率不如ArrayList高;

vector子类只能在考虑线程并发访问的情况下使用。

public synchronized void copyInto(Object[] anArray)

Set集合

主要特点是重复元素不允许保存在内部

继承结构如下:

public interface Set<E> extends Collection<E>

实例化:

package Java从入门到项目实战.Java类集框架.Set集合;import java.util.Set;public class 基本使用set {    public static void main(String[] args) {        //不能有重复值,有的话会报错        //Exception in thread "main" java.lang.IllegalArgumentException: duplicate element: 世界//        Set<String> all = Set.of(“你好”,"xbhog"世界","世界";        Set<String> all = Set.of“你好”,“xbhog","世界";        System.out.println(all);    }}

Hashset子类:

特点:散列存放,重复元素不允许保存 也就是说:无序存放

继承结构如下:

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable

Hashset保存数据:

package Java从入门到项目实战.Java类集框架.Set集合;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class Hashset保存数据 { //数据采用无序保存的方式,不允许保存重复的数据    public static void main(String[] args) {        ///保存类型为String        Set<String> all = new HashSet<String>();        all.add(小李);        all.add(小红);        all.add("小1");        all.add("小2");        all.add(“小花”;        all.add(“小花”;        System.out.println(all);        Iterator<String> iter = all.iterator();        while(iter.hasNext()){            String str  = iter.next();            System.out.print(str+"、");        }    }}

LinkedHashset子类:JDK1.4加入-解决Hashset无法顺序保存的数据

实现是基于链表保存的数据:增加的顺序是集合的保存顺序,不会保存重复的数据。

package Java从入门到项目实战.Java类集框架.Set集合;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.LinkedList;import java.util.Set;public class 实现LinkHashsetet链 {  //基于链表的操作,保存的数据是按顺序保存的    public static void main(String[] args) {        Set<String> all = new LinkedHashSet<String>();        all.add(“小李老师”);        all.add(“小bai”);        all.add(小明);        all.add(“小黄”);        System.out.println(all);        Iterator<String> iter = all.iterator();        while (iter.hasNext()) {            String str = iter.next();            System.out.println(str + "、");        }    }}

Treset子类:

特点:使集中保存的数据有序排列

其继承结构如下:

public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable

Treset子类继承Abstractset抽象类,实现Navigableset接口(这个接口是排序标准接口,是Set子类)

Treset保存数据:

package Java从入门到项目实战.Java类集框架.Set集合;import java.util.*;public class Treeset子类有序排列 {    ///所有保存的数据按从大到小的顺序(字符按字母大小的顺序进行比较)    public static void main(String[] args) {        Set<String> all = new TreeSet<String>();        all.add("11");        all.add("hello");        all.add("hello");        all.add("world");        all.add("add");        all.add(部署);        all.add(“啊哈”;        System.out.println(all);    }}

优先级:数字排序>字母排序>汉字排序

Treset子类排序分析:

有序数据存储时,该类别根据Comparable接口进行排序;需要注意的是,在复制Compareto()方法时,需要比较类中的所有属性;否则,当某些属性相同时,将被误判为同一对象;导致重复元素判断失败;

package Java从入门到项目实战.Java类集框架.Set集合;import java.util.Set;import java.util.TreeSet;class Member implements Comparable<Member>{    private  String name;    private  int age;    public Member(String name,int age){        this.name = name;        this.age = age;    }    public String toString(){        return "姓名:"+this.name +"、年龄:"+this.age;    }    @Override    public int compareTo(Member per){        if(this.age < per.age) return -1;        else if(this.age > per.age) return 1;  ////年龄相同时比较名称        else {            return this.name.compareTo(per.name);        }    }}public class Treset子类排序分析分析 {    public static void main(String[] args) {        Set<Member> all = new TreeSet<Member>();        all.add(new Member(张三),12));        all.add(new Member(李四,12);        all.add(new Member(王五,20);        all.add(new Member(王五”,20));        all.forEach(System.out::println);    }}

关于compareto的相关描述,可以在源代码下的注释中翻译。

消除重复元素:(非排序集中的重复元素)

依靠两种方法:

  1. Hash码:public int Hashcode();
  2. 对象比较:public boolean equals(Object obj);

在比较对象的过程中,首先使用hashcode()方法与集合中保存的代码进行匹配和比较;如果代码相同,则使用equals()方法依次比较属性;如果全部相同;它是相同的元素;

package Java从入门到项目实战.Java类集框架.Set集合;import java.util.*;class Person{    private String name;    private int age;    public Person(String name,int age){        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (!(o instanceof Person)) return false;        Person person = (Person) o;        if (age != person.age) return false;        if (name != null ? !name.equals(person.name) : person.name != null) return false;        return true;    }    @Override    public int hashCode() {        int result = name != null ? name.hashCode() : 0;        result = 31 * result + age;        return result;    }}public class 消除重复元素 {    public static void main(String[] args) {        Set<Person> all = new HashSet<Person>();        all.add(new Person(张三),19));        all.add(new Person(李四,19);        all.add(new Person(王五,20);        all.add(new Person(王五,20);        all.add(new Person(魏六),66));        all.add(new Person("xbhog",10));        System.out.println(-第一种输入方式-”;        all.forEach((person -> {            System.out.println(person.getName()+"----"+person.getAge());        }));        System.out.println("-第二种输入方式-";        Iterator<Person> iter = all.iterator();        while(iter.hasNext()){            Person per = iter.next();            System.out.println(per.getName() + " "+per.getAge());        }    }}

通过hashset 保存重复元素,然后实现去重操作的两种方法。

集合输出

集合在类框架中的标准输出为:IteratorListIteratorEnumerationforeach;

Iterator迭代输出:

迭代输出:依次判断每个元素,判断它是否有内容,如果有内容就输出。

Iterator接口依靠Iterable接口中的iterate()实例化;

Iterator常用方法:

boolean

hasNext()

Returnstrueif the iteration has more elements.

E

next()

返回迭代中的下一个元素。

default void

remove()

将迭代器返回的最后一个元素(可选操作)从基本集合中删除。

boolean

hasNext()

如果迭代中有更多的元素,则返回true。

实例:

package Java从入门到项目实战.Java类集框架.集合输出;import java.util.Iterator;import java.util.Set;public class Iterator输出Set集合 {    public static void main(String[] args) {        Set<String> all = Set.of("Hello","World","xbhog");        Iterator<String> iter = all.iterator();        while(iter.hasNext()){            String str = iter.next();            System.out.print(str+"、");        }           }}

数据删除问题:

在collection和iterator中都有remove方法;那么应该选择什么呢?

无论三七二十一,Collection都会给你删除,这会导致Java.util.concurrentmodificationexception错误;

而Iterator在迭代时;需要根据存储的数据内容进行判断;

因此,只有Iterator接口中的remove才是实现数据删除的正确方法。

如:

package cn.mldn.demo;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class JavaCollectDemo {    public static void main(String[] args) {        // 假如使用Set.of()或List.of()创建的集合不支持删除操作        Set<String> all = new HashSet<String>();        all.add(小白);                  // 保存数据        all.add("Java");                    // 保存数据        all.add("Java");                    // 保存重复数据        all.add("xbhog");               // 保存数据        Iterator<String> iter = all.iterator();         while (iter.hasNext()) {                // 集合是否有数据            String str = iter.next();           // 获取数据            if ("Java".equals(str)) {                iter.remove() ;                 // 删除当前数据            } else {                System.out.print(str + "、");            }        }    }}

Listiterator双向迭代:

首先区分Iterator的作用:

Iterator从前到后单向输出

Listiterator完成后向前输出

但只有实现Iterator从前到后的输出,才能实现Listiterator从后到前的输出(注意顺序);

因为指针只有在从前到后输出结束后才能执行;

如果顺序相反,则输出为空。

以下扩展方法:

Modifier and Type

Method

Description

boolean

hasPrevious()

如果列表迭代器在反向遍历列表中有更多的元素,则返回true。

E

previous()

返回列表中的前一个元素,并将光标位置向后移动。

实例:实施双向迭代

package Java从入门到项目实战.Java类集框架.集合输出;import java.util.ArrayList;import java.util.List;import java.util.ListIterator;public class Listiteratorator双向迭代输出 {    public static void main(String[] args) {        List<String> all = new ArrayList<String>();        all.add(小李);        all.add(“小宋”);        all.add("xbhog");        ListIterator<String> iter = all.listIterator();        System.out.println(”执行从后到前的操作,必须先执行从前到后的操作,只有这样,指针才能指向后面”;        //如果不按相关操作进行,从后到前的操作输出为空;        System.out.println(从前到后输出:-;        while(iter.hasNext()){            System.out.println(iter.next());        }        System.out.println(从后到前输出:-;        while(iter.hasPrevious()){  ///判断是否有前一个元素            System.out.println(iter.previous());  ///有些元素输出前一个元素        }    }}

Listiterator接口实现了List集合的双向迭代操作。

Enumeration枚举输出:

这种类型的输出是基于Vector集合;相当于依附产品;

常用的接口方法:

Modifier and Type

Method

Description

boolean

hasMoreElements()

测试此枚举是否含有更多元素。

E

nextElement()

如果枚举对象至少有一个要提供的元素,则返回枚举的下一个元素。

实例:输出vector集合数据

package cn.mldn.demo;import java.util.Enumeration;import java.util.Vector;public class JavaCollectDemo {    public static void main(String[] args) {        Vector<String> all = new Vector<String>();      // 实例化Vector        all.add(“小黄”);                              // 保存数据        all.add("Java");                                // 保存数据        all.add("xbhog");                           // 保存数据        Enumeration<String> enu = all.elements() ;          // 获得Enumeration实例        while (enu.hasMoreElements()) {            String str = enu.nextElement() ;            System.out.print(str + "、");        }    }}

请注意,Enumeration只有输出操作没有删除操作。

foreach输出:

没什么好说的,既能实现数组输出,又能支持集合输出;

package cn.mldn.demo;import java.util.HashSet;import java.util.Set;public class JavaCollectDemo {    public static void main(String[] args) {        Set<String> all = new HashSet<String>();            // 实例化Set        all.add(“小黄”);                              // 保存数据        all.add("Java");                                // 保存数据        all.add("xbhog");                           // 保存数据        for (String str : all) {            System.out.print(str + "、");         }    }}

实现foreach自定义输出:

首先要知道实现foreach需要iterator接口的支持;因此,只有在set和List集合中,才能通过foreach实现输出;

如果要实现自定义输出,则需要实例Iterable接口来完成iterator功能;

package cn.mldn.demo;import java.util.Iterator;class Message implements Iterable<String> {// 支持foreach输出    private String[] content = { "Java", "Python", "Ubuntu" };  // 信息内容    private int foot;                   // 操作脚标    @Override    public Iterator<String> iterator() {    // 获得Iterator实例        return new MessageIterator();    }    private class MessageIterator implements Iterator<String> {        @Override        public boolean hasNext() {      // 判断内容是否存在            return Message.this.foot <                 Message.this.content.length;        }        @Override        public String next() {          // 获取数据            return Message.this.content[Message.this.foot++];        }    }}public class JavaCollectDemo {    public static void main(String[] args) {        Message message = new Message();    // Iterable接口实例        for (String msg : message) {        // foreach输出            System.out.print(msg + "、");        }    }}

Map集合

map的集合形式是键值对的方式;

常用方法:

Modifier and Type

Method

Description

V

get(Object key)

Returns the value to which the specified key is mapped, ornullif this map contains no mapping for the key.

V

put(K key, V value)

Associates the specified value with the specified key in this map (optional operation).

static <K,V> Map<K,V>

of()

Returns an unmodifiable map containing zero mappings.

其中Map.of()可将每组数据转换为map进行保存;

使用Map保存Key-Value数据:

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.Collection;import java.util.Map;import java.util.Set;public class 保存Key_Value数据 {    public static void main(String[] args) {//        假如Key重复  则会报错:java.lang.IllegalArgumentException//        假如Value和Key设置为null,则会报错:java.lang.NullPointerException        Map<String,Integer> map = Map.of("one",1,"two",null);        System.out.println(map);//        System.out.println(map.get("one"));//        Put只能在map子类中使用    }}

注意点:

  1. 假如Key重复 则会报错:java.lang.IllegalArgumentException
  2. 假如Value和Key设置为null,则会报错:java.lang.NullPointerException
Hashmap子类:

特点:数据通过散列保存,即无序排列

继承结构:

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

Map集合操作HashMap:

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.HashMap;import java.util.Map;public class HahMap子类 {    public static void main(String[] args) {        Map<String,Integer> map =  new HashMap<String,Integer>();//        Map集合操作///        map.put("One",1);//        map.put("Two",2);//        map.put("Three",3);//        System.out.println(map);//        Map数据的保存方法:        System.out.println(map.put("One",1)); //保存数据,但是保存数据的key不存在,返回nulll        System.out.println(map.put("One",101));  // 返回1,即返回是覆盖的值        map.put("Three",3);        map.put(demo1”,4);        map.put(demo2”,null);        map.put("Te",6);        map.put(null,7);        /*结果        * null、7        * */        System.out.println(map.get(demo2);        System.out.println(map.get(null));    }}

注意两个输出的注释:

///Map数据保存方法:System.out.println(map.put("One",1)); //保存数据,但保存数据的key不存在,返回nullSystem.out.println(map.put("One",101));  // 返回1,即返回是覆盖的值

Key和Value在使用Map保存数据时不能使用null,但使用Hashmap保存数据可以将Key或Value设置为null,当然也可以使用Key=Value=null,但这种实现保存毫无意义。

put方法可以在发生时返回原始内容,以便根据返回结果判断设置的key是否存在;

Hashmap数据扩展操作原理分析:

1) 首先观察结构方法:

设置数据扩展阈值;

public HashMap() {    // all other fields defaulted    this.loadFactor = DEFAULT_LOAD_FACTOR; }

然后跳转DEFAULT_LOAD_FACTOR查看:

功能:容量扩展阈值

/**     * The load factor used when none specified in constructor.     */static final float DEFAULT_LOAD_FACTOR = 0.75f;

通过源码可以发现,每个Hashmap在实例化对象时都考虑到了数据存储的扩展;

2) 在Hashmap中观察put方法

public V put(K key,V value){    return putVal(hash(key),key,value,false,true);}

使用put方法保存数据时,会调用putval方法,同时会对key进行哈希处理(生成hash码)

为了方便数据保存,putval()方法将数据封装为Node节点对象,在putval()方法的操作过程中,将使用reasize()方法进行扩展;

3)容量扩充

当保存的数据超过既定的存储容量时,原则如下:

常量地址:DEFAULT_INITIAL_CAPACITY;作为一种初始容量配置,然后1向左移动4-16;

常量默认大小为16个元素,即默认可以保存的最大内容为16个元素;

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

当保存的数据内容超过设定阈值时DEFAULT_LOAD_FACTOR = 0.75f

相当于容量x阈值 = 16*0.75 = 12;也就是说,当保存到12个元素时,容量会扩大;

扩展模式为两倍扩展:即每次扩展容量的两倍。

4)大数据下的数据存储模式:

JDK1.8后来到大数据时代,引发了Hashmap在大数据量中的访问效率;

它提供了一个重要的常量:TREEIFY_THRESHOLD

static final int TREEIFY_THRESHOLD = 8;

使用Hashmap保存时,如果保存的数据数量不超过阈值8,则以链表的形式存储数据;如果超过此阈值,链表将转换为红黑树,以实现树的平衡;并使用左右旋转来确保数据的查询性能。

LinkedHashmap子类:

特点:以链表形式实现偶对存储,可保证存储顺序与数据增加顺序相同;

继承结构:

public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>

使用LinkedHashMao子类存储数据:

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.LinkedHashMap;import java.util.Map;public class LinkedHashMap子类存储数据 {    public static void main(String[] args) {        Map<String,Integer> map = new LinkedHashMap<String,Integer>();        map.put(张三,1);        map.put(李四);        map.put(王五”,3);        map.put(null,3);        map.put(赵六),null);        System.out.println(map);    }}

可以发现,集合保存的顺序与数据增加的顺序相同;同时,LinkedHashmap子类允许保存的Key或value内容为null;

Hashtable子类:

其继承结构如下:

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable

使用Hashtable子类保存数据:

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.LinkedHashMap;import java.util.Map;public class LinkedHashMap子类存储数据 {    public static void main(String[] args) {        Map<String,Integer> map = new Hashtable<String,Integer>();        map.put(张三,1);        map.put(李四);        System.out.println(map);    }}

Hashmap和Hashtable的区别:

Hashmap中的 方法是异步操作(非线程安全),允许在Hashmap中保存null数据

Hashtable中的方法是同步操作(线程安全),但效率慢,Hashtable不允许保存Null数据;否则,Nullpointexception将出现;

TreeMap子类:

特点:Treemap属于有序的Map集合类型;可以按key排序;因此,需要Comaprable接口配合;

继承结构如下:

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable

数据Key对TreMap子类进行排序:

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.Map;import java.util.TreeMap;public class TreeMap子类数据Key排序 {    public static void main(String[] args) {//        由于该程序保存的Key属于String类型,Comparable接口在String中实现,因此///        可根据保存的字符编码由低到高进行排序        /*        * public final class String            implements java.io.Serializable, Comparable<String>, CharSequence        *        *        * */        Map<String,Integer> map = new TreeMap<String,Integer>();        map.put("C",3);        map.put("B",2);        map.put("A",1);        System.out.println(map);    }}

Map.Entry内部接口:

Map可以在JDK1.9开始时创建Map接口.entry内部接口实例;

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.Map;public class Map_Entry内部接口 {    public static void main(String[] args) {        Map.Entry<String,Integer> entry = Map.entry("One",1);        System.out.println(entry.getKey());        System.out.println(entry.getValue());        //观察使用的子类        System.out.println(entry.getClass().getName());    }}

在程序中继续宁Map.当Entry对象构建时,只有引入Key和Value才会自动使用KeyValueHolder子类实例Map.Entry接口对象。

Iterator输出Map集合:

集合数据输出的标准形式是基于Iterator接口;Collection接口直接提供iterator方法,以获得iterator接口实例;但是,由于Map接口中保存的数据是多个Map.Entry接口包装的二元偶对象必须采用Map集合的迭代输出;

  1. 使Map接口中的entrySet(),Map集合变成Set集合;
  2. 获得Set接口实例后,可以使用iterator方法获得iterator的实例对象;
  3. 使用iterator迭代找到每个Map.Entry对象,以及Key和Value的分数。

Iterator和foreach输出Map集合:

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;public class Map集合输出问题 {    public static void main(String[] args) {        Map<String,Integer> map = new HashMap<String,Integer>();        map.put("One",1);        map.put("two",2);//        Key和Value在输出map中的值        Set<Map.Entry<String, Integer>> set = map.entrySet();////将Map集合转换为Set集合        Iterator<Map.Entry<String,Integer>> iter = set.iterator();  //获得Iterator接口        while(iter.hasNext(){/////)          Set中存的都是Mapp.Entry()对象            Map.Entry<String, Integer> me = iter.next();            System.out.print(me.getKey()+" "+me.getValue());        }//        System.out.println("\n");        ///foreach循环输出Map集合:        for(Map.Entry<String,Integer> entry:set){            System.out.print(entry.getKey()+" "+entry.getValue());        }    }}

自定义Key类型:

以自定义的形式实现,但作为Key类型,由于需要数据搜索,必须在类中复制hashcode()和equals()方法。

package Java从入门到项目实战.Java类集框架.Map集合;import java.util.HashMap;import java.util.Map;class Member{    private String name;    private int age;    public Member(String name,int age){        this.name = name;        this.age = age;    }    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 boolean equals(Object o) {        if (this == o) return true;        if (!(o instanceof Member)) return false;        Member member = (Member) o;        if (age !(o instanceof Member)) return false;        Member member = (Member) o;        if (age != member.age) return false;        if (name != null ? !name.equals(member.name) : member.name != null) return false;        return true;    }    @Override    public int hashCode() {        int result = name != null ? name.hashCode() : 0;        result = 31 * result + age;        return result;    }}/** Key自定义;作为Key类型,由于数据搜索的需要,因此,HashCode()应该在类中复制 equals();* */public class 定制Key的值 {    public static void main(String[] args) {        Map<Member,String> map = new HashMap<Member,String>();        map.put(new Member(张三,22),xbhog");        map.put(new Member(李四,23),"博客");        map.put(new Member(王五,26),welcome");        System.out.println(map.get(new Member(张三,22));    }}

key在存储大量数据时可能会出现重复问题,称为Hash冲突;

解决方案:

链地址法(拉链法)、开放寻址,再哈希,建立公共溢出区;