Map(双列集合框架)

1、Map接口及实现类概述

Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序 定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类。

注:将可变对象用作映射键时必须格外小心。当对象是映射中某个键时,如果以影响 equals 比较的方式更改了对象的值,则映射的行为将是不确定的。此项禁止的一种特殊情况是不允许某个映射将自身作为一个键包含。虽然允许某个映射将自身作为值包含,但请格外小心:在这样的映射上 equals 和 hashCode 方法的定义将不再是明确的。

所有通用的映射实现类应该提供两个“标准的”构造方法:一个 void(无参数)构造方法,用于创建空映射;一个是带有单个 Map 类型参数的构造方法,用于创建一个与其参数具有相同键-值映射关系的新映射。实际上,后一个构造方法允许用户复制任意映射,生成所需类的一个等价映射。尽管无法强制执行此建议(因为接口不能包含构造方法),但是 JDK 中所有通用的映射实现都遵从它。

此接口中包含的“破坏”方法可修改其操作的映射,如果此映射不支持该操作,这些方法将抛出 UnsupportedOperationException。如果是这样,那么在调用对映射无效时,这些方法可以(但不要求)抛出外汇返佣UnsupportedOperationException。例如,如果某个不可修改的映射(其映射关系是“重叠”的)为空,则对该映射调用 putAll(Map) 方法时,可以(但不要求)抛出异常。

某些映射实现对可能包含的键和值有所限制。例如,某些实现禁止 null 键和值,另一些则对其键的类型有限制。尝试插入不合格的键或值将抛出一个未经检查的异常,通常是 NullPointerException 或 ClassCastException。试图查询是否存在不合格的键或值可能抛出异常,或者返回 false;某些实现将表现出前一种行为,而另一些则表现后一种。一般来说,试图对不合格的键或值执行操作且该操作的完成不会导致不合格的元素被插入映射中时,将可能抛出一个异常,也可能操作成功,这取决于实现本身。这样的异常在此接口的规范中标记为“可选”。

此接口是 Java Collections Framework 的成员。

Collections Framework 接口中的很多方法是根据 equals 方法定义的。例如,containsKey(Object key) 方法的规范中写道:“当且仅当此映射包含针对满足 (key == null ? k==null : key.equals(k)) 的键 k 的映射关系时,返回 true”。不 应将此规范解释为:调用具有非空参数 key 的 Map.containsKey 将导致对任意的键 k 调用 key.equals(k)。实现可随意进行优化,以避免调用 equals,例如,可首先比较两个键的哈希码(Object.hashCode() 规范保证哈希码不相等的两个对象不会相等)。一般来说,只要实现者认为合适,各种 Collections Framework 接口的实现可随意利用底层 Object 方法的指定行为。

|---Map接口:存储的是一对一对的数据:key-value

|----HashMap:主要实现类;线程不安全的,效率高;允许添加null的key或null的value

|----LinkedHashMap:是HashMap的子类,可以实现照添加的顺序实现遍历。(因为使用了一对双向链表记录添加元素的先后顺序),对于频繁的遍历操作,建议使用此类。

|----TreeMap:可以照元素key的指定的属性的大小实现遍历。底层使用红黑树实现。

|----Hashtable:古老实现类;线程安全的,效率低;不允许添加null的key或null的value

|----Properties:常用来处理属性文件。key和value都是String类型。

2、关于对Map<key,value>的理解

Map中的key是无序的、不可重复的。key构成的集合是Set   --->需要重写必要的hashCode()和equals()。

Map中的value是无序的、可重复的。value构成的集合是Collection  --->需要重写必要的equals()。

Map中的一个键值对构成一个entry。

Map中的entry是无序的、不可重复的。entry构成的集合是Set。

3、常用方法

增:put(Object key,Object value)

删:remove(Object key)

改:put(Object key,Object value)

查:get(Object key)

长度:size()

遍历:keySet() 、 values()、entrySet()

4、内部结构实现原理****

很重要,必须要掌握。

4.1 HashMap在jdk7中实现原理:

HashMap map = new HashMap();//Entry[] table = new Entry;

...

map.put(key1,value1);// key1,value1会封装在一个entry对象中。将此对象存放到table数组中

将key1,value1添加到table中,首先根据key1所在类的hashCode()方法,计算key1的哈希值1,然后使用某种算法,得到哈希值2。 哈希值2再使用indexFor()方法得到其在底层table数组中的存放位置:index。(0<= index <= 15)

->如果index位置上没元素,则key1,value1直接添加成功。----添加成功操作1

->如果index位置上元素(key2,value2)(或已经存在一个链表结构),则比较key1和key2(或链表上每个key的哈希值.

->如果二者(或比较多个key以后)的哈希值不同,则(key1,value1)添加成功。  ----添加成功操作2

->如果二者的哈希值相同,则调用key1所在类的equals(),将key2作为参数传递到此方法中,比较两个key是否equals

->如果返回值为false:则(key1,value1)添加成功。----添加成功操作3

->如果返回值为true:则value1替换原key2对应的value2. ----修改成功

说明:添加成功操作1:将key1,value1存放到数组的位置上。

添加成功操作2,添加成功操作3:将key1,value1添加到链表上。存放到链表头部

扩容的情况:当添加的数据达到临界值(= 数组的长度 * 加载因子)时,则进行扩容。默认的临界值为:16 * 0.75 = 12。默认扩容为原来的2倍。

数组的长度:DEFAULT_INITIAL_CAPACITY:16

加载因子:DEFAULT_LOAD_FACTOR:0.75

threshold:临界值 = 数组的长度capacity * 加载因子loadFactor。

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

jdk 8:数组+单向链表+红黑树

1.当使用空参的构造器,创建对象时,底层并没创建长度为16的数组。

2.当我们首次调用put()添加数据时,底层会首先创建长度为16的数组。

3.底层创建的数组为:Node[]. (class Node implements Map.Entry)。

4.当某个索引位置上的链表长度>8,且数组的总长度>64时,将此索引位置上的元素修改为使用红黑树进行存储。

5.形成链表时,新添加的元素在链表的结尾。

5.3 LinkedHashMap的底层实现原理

LinkedHashMap的底层实现:在HashMap底层结构的基础上,添加了双向链表。

底层实现:

//LinkedHashMap的内部类Entry,定义如下:

static class Entry<K,V> extends HashMap.Node<K,V> {

Entry<K,V> before, after;//双向链表结构

Entry(int hash, K key, V value, Node<K,V> next) {

super(hash, key, value, next);

}

}

主要定义一个静态类,创建了一个before前置节点和一个after后置节点。

5.4 TreeMap的实现

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

Java的TreeMap是集合框架中的一个实现类,TreeMap继承了AbstractMap。

TreeMap实现了NavigableMap接口,提供了多种方便的查找功能;

TreeMap实现了Cloneable接口,可以克隆;

TreeMap实现了Serialiable接口,可以序列化。

TreeMap常用方法:

public V put(K key, V value) 添加一对键值对

public V remove(Object key) 删除对应的键值对

public void clear() 删除所有元素

public Map.Entry<K,V> ceilingEntry(K key) 返回map中键值不小于参数key的最小键值对应的键值对,如果没有则返回null

public final boolean containsKey(Object key) 判断是否含有某一键值

public boolean containsValue(Object value) 判断是否含有某一value

public V replace(K key, V value) 修改一对键值对

public Comparator<? super K> comparator() 返回该TreeMap的比较器

接下来new一个TreeMap简单实现一下Map提供的一些方法:

public class TreeMapTest {

public static void mapain(String[] args) {

Map<String,Integer> map = new TreeMap<String,Integer>();

//添加

map.put("疯狂Java讲义", 109);

map.put("疯狂Android讲义", 89);

map.put("疯狂Python讲义", 179);

map.put("疯狂Htmapl讲义", 119);

map.put("疯狂Ajax讲义", 109);

//修改

map.put("疯狂Ajax讲义", 18);

System.out.println("是否包含值为 疯狂Java讲义 key"+

map.containsKey("疯狂Java讲义"));

System.out.println("是否包含值为 89 key"+

map.containsValue(89));

//迭代器遍历遍历value:values()

Collection<Integer> values = map.values();

Iterator<Integer> iterator = values.iterator();

while(iterator.hasNext()){

System.out.println(iterator.next());

}

//遍历key-value方式一:keySet()+map.get(key)

for(Object obj : map.keySet()){

System.out.println(obj + "--->" + map.get(obj));

}

//遍历key-value方式二entrySet()

Set<Entry<String, Integer>> entrySet = map.entrySet();

Iterator<Entry<String, Integer>> iterator2 = entrySet.iterator();

while(iterator2.hasNext()){

// 修改遍历出样式

// mapap.Entry entry = (mapap.Entry)iterator2.next();

// System.out.println(entry.getKey()+"---->"+entry.getValue());

System.out.println(iterator2.next());

}

map.clear();    //清空map

System.out.println(map.isEmpty());   //是否为空

}

}

5.5 使用Properties读取配置文件

//处理属性文件

public void test1() throws FileNotFoundException, IOException{

Properties pros = new Properties();

pros.load(new FileInputStream("jdbc.properties"));

String user = pros.getProperty("user");

System.out.println(user);

}

涉及了I/O那块的内容,通常都是用Properties类来读取数据库连接的一些数据,到后面就知道了。

Collections工具类(与Math一样,直接调用就OK了)

1.作用:

是一个操作 Set、List 和 Map 等集合的工具类

2.常用方法:

reverse(List):反转 List 中元素的顺序

shuffle(List):对 List 集合元素进行随机排序

sort(List):根据元素的自然顺序对指定 List 集合元素升序排序

sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序

swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素

Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素

Object min(Collection):根据元素的自然顺序,返回给定集合中的最大元素

Object min(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素

int frequency(Collection,Object):返回指定集合中指定元素的出现次数

void copy(List dest,List src):将src中的内容复制到dest中

boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所旧值

Map

Collection接口

-List接口

-Set接口

Map接口

1.存放key-value数据

key:不能重复 底层实现使用set

value:可以重复 底层实现用Collection

2.实现类

①.HashMap:主要实现类

②.LinkedHashMap:使用链表的方式维护添加Map元素的顺序

③.TreeMap

④.Hashtable:线程安全低,不建议使用

子类Properties:通常用来处理属性文件,键和值都是String类型

3.常用方法

Object put(Object key,Object value):添加元素

Object remove(Object key):移除元素 删除一个Key-value

void putAll(Map t)

void clear()

Object get(Object key):获取指定value值,若没有找到对应的key值,则返回null

boolean containsKey(Object key)

boolean containsValue(Object value)

int size()

boolean isEmpty()

boolean equals(Object obj)

Set keySet()

Collection values()

Set entrySet()

@Test

public void testMap1() {

Map map = new HashMap<>();

map.put("A", 123);

map.put("B", 456);

map.put("C", null);

map.put("B", 123);

map.put(new Person("D", 20), 110);

// 获取元素个数

System.out.println(map.size());

System.out.println(map);

// 移除元素

map.remove("B");

System.out.println(map);

// 更新value值(相当于修改,Set中set方法)

map.put("C", 119);

System.out.println(map);

// 获取元素

Object object = map.get("A");

System.out.println(object);

// 判断是否包含某个Key值

boolean iscontainsKey = map.containsKey("C");

System.out.println(iscontainsKey);

}

结果:

4

{A=123, B=123, C=null, Person [name=D, age=20]=110}

{A=123, C=null, Person [name=D, age=20]=110}

{A=123, C=119, Person [name=D, age=20]=110}

123

true

Map的遍历

1.Map中的key是使用Set存放,不可重复

2.Map中的value使用Collection来存放,可以重复

3.一个key-value,是一个Entry,Entry使用Set来存放,也是不可重复

4.在向Map中添加元素时,会调用key所在类的equals()方法,判断两个key是否相同 如果相同,添加的是后面的元素

5.遍历Map集合的常用方法 Set keySet() Collection values() Set entrySet()

@Test

public void testMap2() {

// 1.遍历key的集合

Map map = new HashMap<>();

map.put("刘备", 48);

map.put("关羽", 30);

map.put("张飞", 25);

map.put(null, null);

Set set = map.keySet();

for (Object obj : set) {

System.out.println(obj);

}

// 2.遍历value的集合

System.out.println("---------------------");

Collection values = map.values();

Iterator iterator = values.iterator();

while (iterator.hasNext()) {

System.out.println(iterator.next());

}

System.out.println("-------------------");

// 3.遍历key-value对

// 方式一

Set set2 = map.keySet();

for (Object obj : set2) {

/*Object key = obj;

Object value = map.get(obj);*/

System.out.println("key:"+obj+"-value:"+map.get(obj));

}

System.out.println("-------------------");

//方式二

Set set3 = map.entrySet();

for (Object object : set3) {

Map.Entry  entry=(Entry) object;

Object key=entry.getKey();

Object value=entry.getValue();

System.out.println(key+":"+value);

}

}

结果:

关羽

null

张飞

刘备

---------------------

30

null

25

48

-------------------

key:关羽-value:30

key:null-value:null

key:张飞-value:25

key:刘备-value:48

-------------------

关羽:30

null:null

张飞:25

刘备:48

Java集合中的Map接口怎么使用?的更多相关文章

  1. Java集合中的Map接口

    jdk1.8.0_144 Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap.TreeMap.So ...

  2. Java集合框架之Map接口浅析

    Java集合框架之Map接口浅析 一.Map接口综述: 1.1java.util.Map<k, v>简介 位于java.util包下的Map接口,是Java集合框架的重要成员,它是和Col ...

  3. Java中的集合(十三) 实现Map接口的Hashtable

    Java中的集合(十三) 实现Map接口的Hashtable 一.Hashtable简介 和HashMap一样,Hashtable采用“拉链法”实现一个哈希表,它存储的内容是键值对(key-value ...

  4. Java中的集合(十一) 实现Map接口的TreeMap

    Java中的集合(十一) 实现Map接口的TreeMap 一.TreeMap简介(基于JDK1.8) TreeMap是基于红黑树数据结构,是一个key-value的有序集合,该映射根据其键的自然顺序进 ...

  5. Java集合中List,Set以及Map等集合体系详解

    转载请注明出处:Java集合中List,Set以及Map等集合体系详解(史上最全) 概述: List , Set, Map都是接口,前两个继承至collection接口,Map为独立接口 Set下有H ...

  6. Java集合中List、Set以及Map

    概述: List , Set, Map都是接口:List , Set继承至Collection接口,Map为独立接口 Set下有HashSet,LinkedHashSet,TreeSet List下有 ...

  7. Java集合中Comparator和Comparable接口的使用

    在Java集合中,如果要比较引用类型泛型的List,我们使用Comparator和Comparable两个接口. Comparable接口 -- 默认比较规则,可比较的 实现该接口表示:这个类的实例可 ...

  8. 第19章 集合框架(3)-Map接口

    第19章 集合框架(3)-Map接口 1.Map接口概述 Map是一种映射关系,那么什么是映射关系呢? 映射的数学解释 设A,B是两个非空集合,如果存在一个法则,使得对A中的每一个元素a,按法则f,在 ...

  9. Java集合框架之Collection接口

    Java是一门面向对象的语言,那么我们写程序的时候最经常操作的便是对象了,为此,Java提供了一些专门用来处理对象的类库,这些类库的集合我们称之为集合框架.Java集合工具包位于Java.util包下 ...

随机推荐

  1. [转载]MinGW安装过程

    本文转自https://blog.csdn.net/my_wade/article/details/46941645 MinGW安装过程 一. 下载 MinGW官网下载地址:http://source ...

  2. redis数据操作篇

    服务器端 服务器端的命令为redis-server 可以使⽤help查看帮助⽂档 redis-server --help 个人习惯 ps aux | grep redis 查看redis服务器进程su ...

  3. 笔记62 Spring Boot快速入门(二)

    SpringBoot部署 一.jar方式 1.首先安装maven. <1>下载最新的maven版本:https://maven.apache.org/download.cgi <2& ...

  4. 笔记59 Spring+Hibernate整合(二)

    一.项目结构 二.创建表 数据库中只有一张表,stock,三个字段:stock_id.stock_code和stock_name. CREATE TABLE `stock` ( `STOCK_ID` ...

  5. spring boot 项目的创建

    一. 进入https://start.spring.io 快速创建项目 二. 利用eclipse sts插件创建项目 1. 安装sts插件 进入https://spring.io/tools3/sts ...

  6. pip install RISE报错解决

    ERROR: Cannot uninstall 'tornado' ERROR: Cannot uninstall 'tornado'. It is a distutils installed pro ...

  7. 【Flutter学习】基本组件之基本列表ListView组件

    一,概述 列表是前端最常见的需求. 在flutter中,用ListView来显示列表页,支持垂直和水平方向展示,通过一个属性我们就可以控制其方向,列别有以下分类 水平列表 垂直列表 数据量非常大的列表 ...

  8. 树的直径变形——cf1238F

    /* 题目给定一些一维线段[li,ri],要求从这些线段里挑出一些线段,每条线段对应一个点,如果两线段相交,那么点连边,这样得到的树是good-tree 现在给定一棵树,要求从该树中选出一棵子树,使这 ...

  9. Linux环境下安装PHP的memced扩展

    先下载libmemcached: wget  https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.t ...

  10. API函数ShellExecute与ShellExecuteEx用法

    ShellExecute: 1.函数功能:你可以给它任何文件的名字,它都能识别出来并打开它.2.函数原型: HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpO ...