`

Map、List等集合

 
阅读更多

编程思想是相通的,只是实现方式有所不同。

       数据库中,我们常常用索引来找到具体某个值,当然会经常用联合索引。而在开发中,常常会有种情况:集合的key使用自定义类对象,需要自己实现hashCode()和equal()方法。

 

再来看看Map、List、Set等集合的实现:

一、Map,以hashMap为例,

1)初始化为长度16的数组,数组每个元素为一个链表对象。

2)当新建链表元素个数超过threshold,数组长度就扩展2倍。

3)当put时候,用if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 来判断是否(Object) key相等。

int threshold = (int)Math.min(capacity(16) * loadFactor(0.75f), MAXIMUM_CAPACITY(1 << 30) + 1);

另外,在java8中,HashMap加入了红黑树结构,当链表元素较多(默认8个)时,链表就会转化为红黑树。

而TreeMap实现也是基于红黑树的。可参考 

TreeMap:由红黑树实现,与HashMap不同,他内部元素不是数组,而是一个树型结构。身为排序二叉树,所以他是有序的。

 

二、List,以ArrayList为例,

1)初始化为长度10的数组,数组每个元素为一个Object。

2)当新添加对象的坐标index大于数据长度,就扩展增加当前数组1/2的长度。

3)当add时候,已有对象的size++,超过数组长度就扩展,当调用set(int index, E element)方法时,传值大于新添加对象的坐标时会报错。

 

三、Set,以hashSet为例,

1)其实用一个HashMap成员变量来实现,所以特性和hashMap基本一致。

而其他Set实现类等也是如此,比如TreeSet用TreeMap实现。

 

并发:

1、可以使用concurrent包下面的类,比如ConcurrentHashMap<K, V>和CopyOnWriteArrayList<E>等。

2、自己加锁并发。其中用Iterator遍历时,增删元素时也需要对集合加锁。

 

jdk1.7以及之前版本ConcurrentHashMap实现Segment锁分段。每个Segment下面是多个Node,jdk7是Segment+HashEntry。

jdk1.8版本ConcurrentHashMap实现:采用Node + CAS + Synchronized,有点像java8的hashmap,使用数组+链表+红黑树,保留锁分段思想。使用较多CAS算法(即unsafe.compareAndSwapInt(this, valueOffset, expect, update)),这样可非阻塞无锁插入,但在默认操作hash值相同的链表还是会synchronized头结点上锁,将新值放在node最后一个后面,这样才能保证线程安全,和以前一样。

put方法:1.6直接获取锁,1.7自旋锁(UNSAFE.get),等待其他人操作完,1.8是链表为null直接cas乐观锁,否则Node链表加锁。

get方法:1.6乐观锁,直接获取值,为null则可能正处于put,需要再加过判断一次。1.7HashEntry的乐观锁(UNSAFE.get)。1.8Node的乐观锁(UNSAFE.get)。

针对:

get操作的高效之处在于采用分段锁,且整个get过程不需要加锁,除非读到的值是空的才会加锁重读,特性如下:

1、写用分段锁:每个Segment包含一个数组元素,每个元素是一个HashEntry<K,V>的链表,而且put添加元素时放在头部,不影响读取。至于remove中间元素,会设置链表元素的next属性(volatile修饰)。

2、get操作不加锁:get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。之所以不会读到过期的值,是根据java内存模型的happen before原则,对volatile字段的写入操作先于读操作,即使两个线程同时修改和获取volatile变量,get操作也能拿到最新的值,

static final class HashEntry<K,V> {
        final int hash;
        final K key;
        volatile V value;
        volatile HashEntry<K,V> next;

        HashEntry(int hash, K key, V value, HashEntry<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
}

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    map/list集合转化成xml字符串 xml字符串转化成map/list集合

    本篇文章将详细介绍如何将Map和List集合转换为XML字符串,以及如何将XML字符串反向转换回Map和List集合。 首先,让我们探讨`Map`集合转成XML字符串的过程。一个`Map`对象存储键值对,可以使用各种库如`JAXB (Java ...

    易语言仿java集合 list map源码

    本主题聚焦于易语言中的面向对象编程,特别是模仿Java集合框架的List和Map接口的实现。这些数据结构在编程中扮演着核心角色,用于组织和管理数据。 首先,让我们深入了解易语言的面向对象编程概念。面向对象编程...

    Map拆分List拆分

    Map拆分与List拆分涉及到数据的分布式处理,这通常在Hadoop、Spark等大数据处理框架中常见。下面我们将详细探讨这两个概念及其在实际应用中的重要性。 首先,Map是一种键值对存储的数据结构,其中每个键(Key)都是...

    不用遍历的方式在对象集合list中抽取属性集合转化为map或list

    首先新建一个实体类Person @Data public class Person { /** 编码 */ private String code; /** 名字 */ ...实例化三个对象放入list集合中 public static void main(String[] args) { Person pe

    List转换为List

    5. **返回新的List&lt;Map&gt;**:最终返回包含Map对象的List集合。 #### 示例代码: 假设有一个AnnouncementBean类,包含属性:actid(ID),acttitle(标题),actcon(内容),acttime(时间),usid(发布人),...

    ResultSet 转为listmap

    2. 便于数据展示:List&lt;Map&gt; 可以方便地将查询结果集展示在 GUI 组件中,如 JTable、DataGridView 等。 在实际开发中,我们可以根据需要对 ResultSetToList 方法进行修改和扩展,以满足不同的业务需求。 知识点: ...

    JAVA集合map、list、set详解

    详细描述map、list、set的常用子类特性,各个场景的适用。

    java字符串与集合互相转换,字符串转List,Map,List转String,String转List源码

    List集合转换成String,String转List,Map转String,String转Map等 集合与字符串相互转换,可以自己扩展源码,带有注释

    在Java 8中将List转换为Map对象方法

    在Java 8中将List转换为Map对象方法 在Java 8中,将List转换为Map对象是一种非常实用的技术,特别是在处理大规模数据时非常有用。本文将详细介绍在Java 8中将List转换为Map对象的方法,并提供了多种实现方式。 ...

    集合概述set、List、Map

    ### 集合概述:set、List、Map #### 一、集合框架概述 ##### 1.1.1 容器简介 在Java编程中,集合框架是一个非常重要的概念,它提供了一种灵活的方式来存储、操作和管理不同类型的对象集合。集合框架的主要目标是...

    jQuery的Ajax实现异步传输List、Map

    通过正确配置Ajax请求和服务器接口,你可以轻松地传递和处理List、Map等复杂数据结构,提升Web应用的交互体验。在实际项目中,确保对错误处理和安全性有充分考虑,这将有助于构建健壮和安全的Web应用。

    嵌套Map或者List获取key、value值

    例如,我们可以有一个用户信息的Map,其中键是用户ID,而对应的值是一个包含用户名、邮箱等信息的另一个Map。 ```java Map, Map, String&gt;&gt; users = new HashMap(); ``` 获取嵌套Map的key和value通常涉及两个步骤:...

    Hibernate常见集合映射(Set,List_Array,Map,Bag)

    常见的集合映射类型有 Set、List、Array、Map 和 Bag 等,每种类型都有其特点和应用场景。 Set 集合映射 Set 集合是 Hibernate 中基础的集合类型,元素数据一般使用外键同主表关联。Set 集合非常适用于集合元素不...

    (数组 list集合 map集合 Object对象 XML数据格式) 转成 string json

    (数组 list集合 map集合 Object对象 XML数据格式) 转成 string json

    List set map集合容器的区别

    根据给定文件的信息,我们可以详细地探讨一下Java中几种主要的集合容器——List、Set以及Map的区别,并且深入了解它们各自的特性和应用场景。 ### 一、List #### 1. ArrayList - **特点**:`ArrayList`是基于动态...

    自己对List,Set,Map等集合类的理解

    在Java编程语言中,集合框架是处理对象组的重要工具,其中List、Set和Map是最基本的接口,分别代表了有序的列表、无序的集合和键值对的映射关系。下面将详细解释这些集合类及其特点。 1. **List接口**: List是一...

    jdk1.8list转map的测试类

    list转map的测试类,用到jdk1.8的新特性,感觉用起来很方便

    map转化为list

    在Java中,Map是一种存储键值对的数据结构,而List则是一个有序的元素集合。Map不能直接转换为List,但可以通过一些方法实现。一种常见的方式是创建一个新的List,然后遍历Map的entrySet(),将每个键值对作为新List...

    Java集合:Collection、List、Set、Map使用详解

    本文将深入探讨Java集合框架中的四个主要接口:Collection、List、Set和Map,以及它们的实现原理。 ### 集合框架概述 集合框架是Java API中用于存储和管理对象的统一框架。它为数据结构提供了抽象接口,使得程序员...

    hibernate map 集合映射

    在Hibernate的映射文件(.hbm.xml)中,我们通常使用`&lt;set&gt;`, `&lt;list&gt;`, `&lt;map&gt;`等标签来定义集合映射。每个标签都有对应的属性,例如: - `name`: 对象属性名。 - `table`: 所映射的数据库表名。 - `inverse`: ...

Global site tag (gtag.js) - Google Analytics