- 浏览: 913442 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (537)
- Java SE (114)
- Struts (18)
- Hibernate (25)
- Spring (3)
- Page_Tech (41)
- Others (87)
- Database (29)
- Server (24)
- OpenSource_Tools (15)
- IDE_Tool (22)
- Algorithm (28)
- Interview (22)
- Test (28)
- Hardware (1)
- Mainframe (25)
- Web application (4)
- Linux (3)
- PHP (17)
- Android (1)
- Perl (6)
- ubuntu (1)
- Java EE (9)
- Web Analysis (5)
- Node.js (2)
- javascript (2)
最新评论
-
一键注册:
request.getRequestURL()和request.getRequestURI() -
SuperCustomer:
...
SED的暂存空间和模式空间 -
juyo_ch:
讲得挺好理解的,学习了
java 死锁及解决 -
chinaalex:
最后一题答案正确,但是分析有误.按照如下过程,上一行为瓶,下一 ...
zz智力题 -
liaowuxukong:
多谢博主啦,弱弱的了解了一点。
C++/Java 实现多态的方法(C++)
java5的java.util包提供了大量集合类。其中最常用的集合类有List、Set、Map等。这篇文章主要介绍其中的Map。
首先,来看下java.util包中Map相关的集合类的类图。
接口Map是整个类图的跟,Map往下又提供了两个接口:ConcurrentMap和SortedMap。ConcurrentMap是java5中新增的线程安全的Map接口;而SortedMap则是支持排序的Map接口。在下面这些具体的实现类中,常用的就属Hashtable、HashMap和TreeMap了。另外,java5新增了HashMap的并发版本ConcurrentHashMap。下面主要介绍下这几个类。
在开始之前,先介绍下Map是什么?
javadoc中对Map的解释如下:
This interface takes the place of the Dictionary class, which was a totally abstract class rather than an interface.
The Map interface provides three collection views, which allow a map's contents to be viewed as a set of keys, collection of values, or set of key-value mappings.
从上可知,Map用于存储“key-value”元素对,它将一个key映射到一个而且只能是唯一的一个value。
Map可以使用多种实现方式,HashMap的实现采用的是hash表;而TreeMap采用的是红黑树。
1. Hashtable 和 HashMap
这两个类主要有以下几方面的不同:
Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类。
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。 当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。而在Hashtable中,无论是key还是value都不能为null 。
这两个类最大的不同在于Hashtable是线程安全的,它的方法是同步了的,可以直接用在多线程环境中。而HashMap则不是线程安全的。在多线程环境中,需要手动实现同步机制。因此,在Collections类中提供了一个方法返回一个同步版本的HashMap用于多线程的环境:
- public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
- return new SynchronizedMap<K,V>(m);
- }
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<K,V>(m);
}
该方法返回的是一个SynchronizedMap 的实例。SynchronizedMap类是定义在Collections中的一个静态内部类。它实现了Map接口,并对其中的每一个方法实现,通过synchronized 关键字进行了同步控制。
2. 潜在的线程安全问题
上面提到Collections为HashMap提供了一个并发版本SynchronizedMap。这个版本中的方法都进行了同步,但是这并不等于这个类就一定是线程安全的。在某些时候会出现一些意想不到的结果。
如下面这段代码:
// shm是SynchronizedMap的一个实例
if(shm.containsKey('key')){
shm.remove(key);
}
这段代码用于从map中删除一个元素之前判断是否存在这个元素。这里的containsKey和reomve方法都是同步的,但是整段代码却不是。考虑这么一个使用场景:线程A执行了containsKey方法返回true,准备执行remove操作;这时另一个线程B开始执行,同样执行了containsKey方法返回true,并接着执行了remove操作;然后线程A接着执行remove操作时发现此时已经没有这个元素了。要保证这段代码按我们的意愿工作,一个办法就是对这段代码进行同步控制,但是这么做付出的代价太大。
在进行迭代时这个问题更改明显。Map集合共提供了三种方式来分别返回键、值、键值对的集合:
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K,V>> entrySet();
在这三个方法的基础上,我们一般通过如下方式访问Map的元素:
Iterator keys = map.keySet().iterator();
while(keys.hasNext()){
map.get(keys.next());
}
在这里,有一个地方需要注意的是:得到的keySet和迭代器都是Map中元素的一个“视图”,而不是“副本” 。问题也就出现在这里,当一个线程正在迭代Map中的元素时,另一个线程可能正在修改其中的元素。此时,在迭代元素时就可能会抛出 ConcurrentModificationException异常。为了解决这个问题通常有两种方法,一是直接返回元素的副本,而不是视图。这个可以通过
集合类的 toArray() 方法实现,但是创建副本的方式效率比之前有所降低,特别是在元素很多的情况下;另一种方法就是在迭代的时候锁住整个集合,这样的话效率就更低了。
3. 更好的选择:ConcurrentHashMap
java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashMap。ConcurrentHashMap提供了和Hashtable以及SynchronizedMap中所不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。
上面说到的16个线程指的是写线程,而读操作大部分时候都不需要用到锁。只有在size等操作时才需要锁住整个hash表。
在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。
发表评论
-
maven 在Mac OS下运行的问题总结
2014-05-16 17:24 819在maven下生成基本的项目结构。 生成eclipse项 ... -
【zz】 java函数参数类型后添加三点的用法
2012-07-02 09:48 1042今天看到一个没见过的函数参数列表test(int... a), ... -
【zz】Java编码的理解和Java加载器的理解
2012-06-08 15:59 745一,我对java中编码的理解1. 编码的产生 对电脑而言 ... -
类加载器入门级应用
2012-06-08 15:17 9201、类加载器负责加载 Ja ... -
ClassLoader详解
2012-06-08 14:23 1238Point One 将J2EE应用程序移植到W ... -
Java静态代理与动态代理
2012-05-29 10:32 934JAVA的静态代理与动态代 ... -
JDK的动态代理深入解析(Proxy,InvocationHandler)(转)
2012-05-29 10:31 5179调用处理器InvocationHandle ... -
zz 动态反射实现AOP的简单原理
2012-05-28 17:46 892其实AOP的意思就是面向切面编程. OO注重的是我们 ... -
理解Java枚举在单例模式的应用
2012-06-05 15:50 12685.3.9 单例和枚举 按照《高效Java 第二版》中的说 ... -
Java 枚举的介绍
2012-05-23 16:50 0一、使用简单程序完成枚举的功能 例:使用简单类完成枚举操作 ... -
枚举类型的用法
2012-06-05 15:50 1424DK1.5引入了新的类型——枚举。在 Java 中它虽然算 ... -
单例模式的七种写法 (包括1.5新特性)
2012-05-23 16:18 0第一种(懒汉,线程不安全): <!--<br / ... -
重写hashCode方法的意义
2012-05-23 16:01 1636Java中的很多对象都override了equ ... -
JDK Log的设计思想
2012-05-23 14:39 1305最近在看《Agile Java》,看到日志一节,收获颇多,所以 ... -
[zz] Synchronized和Static Synchronized区别
2012-05-23 14:07 775通过分析这两个用法的分析,我们可以理解java中锁的概念。一 ... -
双精度、单精度的有效位数
2012-05-22 17:25 5093浮点数7位有效数字。(应该是单精度数) 双精度数16位有效 ... -
DecimalFormat 使用方法
2012-05-22 16:44 1019我们经常要将数字进行格式化,比如取2位小数,这是最常见的。Ja ... -
Java Applet 无法运行的一个问题
2012-04-28 15:09 2526当你用JDK1.6开发出的新功能,在JDK1.6上re ... -
设计模式应用场景总结
2012-04-11 16:47 1259在J2EE的开发和测试中,其实不知不觉已经使用了许多设计模式。 ... -
【转】有状态和无状态的Servlet
2012-04-06 14:57 3739我相信有不少人还不明白有状态和无状态(Stateful and ...
相关推荐
1. **泛型(Generics)**:JDK 1.5首次引入泛型,允许在类、接口和方法中使用类型参数,提高了代码的类型安全性和重用性。泛型使得集合类(如List、Set、Map)可以明确地指定元素类型,避免了类型转换异常。 2. **...
1. **泛型(Generics)**:泛型是JDK1.5引入的一项重要功能,它允许在类、接口和方法中定义类型参数,以增强类型安全性,减少运行时的类型转换,并且在编译阶段就能捕获可能存在的类型错误。泛型的使用使得集合框架...
2. **泛型**:泛型是1.5最重要的新特性之一,它允许在类、接口和方法中使用类型参数,增强了类型安全性和代码重用性。泛型可以限制集合元素的类型,避免了类型转换错误。 3. **枚举类(enum)**:之前的Java中,...
### 详细描述 JDK 1.5 新特性:泛型 #### 一、引言 Java 5.0(也称为 JDK 1.5)引入了一系列重要的新特性,这些特性极大地提高了开发者的编程效率和代码质量。其中最显著的特性之一便是泛型(Generics)。本文将...
在压缩包`linux_jdk1.5`中,可能包含的是已解压的JDK文件夹,包括了JRE(Java Runtime Environment)、开发工具(如javac编译器)和其他必要的库文件。开发者可以通过这个解压后的文件夹直接进行Java开发和运行。 ...
1. 泛型(Generics):这是JDK 1.5最显著的变化之一,它允许开发者在定义类、接口和集合时指定类型参数,增强了代码的类型安全性,减少了运行时类型异常的可能性。 2. 自动装箱与拆箱:自动装箱使得基本数据类型和...
今天,JDK1.5終於內建泛型特性,不僅編譯器不再需要 任何外力(外掛附件)的幫助,整個 Java標準程式庫也被翻新(retrofit),許多 角落針對泛型做了改寫。 讓我們把帶有「參數化型別」(parameterized types)的 ...
泛型是JDK 1.5最重要的特性之一,它允许在类、接口和方法中定义类型参数,从而增强了类型安全性和代码重用。例如,可以定义一个通用的集合类`List<T>`,其中T代表任意类型。泛型还可以用于限制方法的参数类型,避免...
1. **泛型(Generics)**:这是JDK 1.5最重要的特性之一,允许在类、接口和方法中声明参数化类型,从而提高了代码的类型安全性和重用性。泛型有助于减少类型转换的错误,并在编译时期就能发现潜在的问题。 2. **...
1. **泛型(Generics)**:这是JDK 1.5中的核心特性之一,它允许在类、接口和方法中使用类型参数,提高了代码的类型安全性和重用性。泛型使得集合框架能够处理特定类型的元素,减少了强制类型转换的需要,并且在编译...
**Java泛型(Generics)**是JDK 1.5引入的一项重要特性,它极大地提高了代码的类型安全性和可读性。泛型主要是为了更好地处理集合类(如List、Set、Map等),避免了类型转换的麻烦和潜在的ClassCastException风险。 ...
1. **Lambda表达式**:这是JDK 1.8最重要的特性之一,它提供了一种简洁的方式来表示匿名函数,简化了处理函数接口和集合的操作。 2. **Stream API**:Stream API允许对集合数据进行声明性处理,提供了大量操作如...
2. **集合框架**:在1.6版本中,Java的集合框架已经相当成熟,包括List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)、Map(如HashMap和TreeMap)等接口及其实现,以及实用工具类`Collections`和`Arrays`...
在本文中,我们将详细探讨JDK 1.8.0_161版本中的关键特性和更新。 ### 1. Java 8新特性 JDK 1.8.0是Java 8的主要版本,引入了许多创新特性,旨在提高代码的可读性、简洁性和性能。以下是一些主要的新特性: #### ...
泛型是JDK 1.5引入的重要特性,允许在类、接口和方法中使用类型参数。在JDK 1.8中,泛型的应用更加广泛,例如在集合框架中,泛型可以确保插入和检索的数据类型安全,避免了不必要的类型转换。 ### 2. Lambda表达式 ...
### Java中Map集合的用法详解 #### 一、引言 在Java编程语言中,`java.util`包内提供了多种强大的数据结构来帮助开发者高效地处理数据。其中,`Map`作为Java中最常用的数据结构之一,被广泛应用于各种场景。`Map`是...
3. 设置环境变量,包括`JAVA_HOME`指向JDK安装目录,`PATH`中添加`%JAVA_HOME%\bin`,确保系统能够找到Java命令。 4. 验证安装,通过命令行输入`java -version`,显示正确版本信息即安装成功。 ### 4. **JDK 1.8的...
文档进一步展示了JDK 1.5中引入的新特性——增强的for循环(也称为“foreach”循环),用于遍历`Map`: ```java Map m = new HashMap(); for (Object o : m.keySet()) { m.get(o); } ``` 这种方法通过`keySet()`...
7. **JDK 版本特性**: JDK 1.5 引入了枚举、匿名内部类、自动装箱/拆箱等特性;JDK 1.7 引入了钻石操作符、try-with-resources 等;JDK 1.8 包括 Lambda 表达式、接口的默认方法和静态方法、Stream API 等。 8. **...