java中Map类
- 格式:doc
- 大小:35.00 KB
- 文档页数:4
package com.baidu.oct4;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import java.util.TreeMap;/*用 Map统计字符串中每个字符出现的个数* (可以加限制条件,只统计英语字母或者汉字等)* */public class TreeSetDemo{public static void main(String [] args){String str = "abcdefyadhisn,xiednefmecd casdxsdffg@$%tjukdfds,生活是一杯酒,生活是一首诗";String count =getCount(str);System.out.println(count);}// 获取统计的方法public static String getCount(String str){char [] ch = str.toCharArray();Map<Character,Integer> map = new TreeMap<Character,Integer>();for (int i = 0; i < ch.length; i++){// 只统计里面英语字母的个数// if(!(ch[i]>'a'&&ch[i]<'z'||ch[i]>'A'&&ch[i]<'Z'))// continue;// 只统计其中汉字个数//// if(!(ch[i]>='一'&&ch[i]<='龥'))// \u4e00 \u9fa5// continue;// 获取字符数组顺序对应的值Integer value = map.get(ch[i]);int count=1;if(value!=null){count = value+1;}map.put(ch[i], count);}return toNewString(map);}//将麻婆 Map 结果转换成自定义格式的字符串public static String toNewString(Map<Character,Integer> map) {StringBuilder sb = new StringBuilder();Iterator <Entry<Character,Integer>> it = map.entrySet().iterator();while(it.hasNext()){Entry<Character, Integer> en = it.next();char cha= en.getKey();int value = en.getValue();sb.append(cha+"{"+value+"}"+" ");}return sb.toString();}}运行效果:统计全部字符串出现次数只统计其中每个汉字出现的次数只统计其中每个英文字母出现的次数。
c#中泛型集合directory和java中map集合对⽐c#中directory的基本⽤法1、创建及初始化 Dictionary<int, string> myDictionary = new Dictionary<int, string>();2、添加元素 myDictionary.Add("C#",0); myDictionary.Add("C++",1); myDictionary.Add("C",2); myDictionary.Add("VB",2);3、查找元素By Key java中式调⽤⽅法keyset放⼊set集合中,然后利⽤Iterator迭代器遍历SET if(myDictionary.ContainsKey("C#")) { Console.WriteLine("Key:{0},Value:{1}", "C#", myDictionary["C#"]); }4.遍历元素 By KeyValuePair 这是⼀种关系,和java中的map.entry< , >类似c# : foreach (KeyValuePair<string, int> kvp in myDictionary) { Console.WriteLine("Key = {0}, Value = {1}",kvp.Key, kvp.Value); }java:set<map.entry< , >> entrySet=map.entrySet();Iterator<map,entry< , >> it=entryset.iterator();//利⽤迭代器便利关系map.entry< , >while(it.hasnext()) { map.entry< , > me= it.next();//这是⼀种关系 me.getkey(); me.getvalue();}5、仅遍历键 By Keys 属性 Dictionary<string, int>.KeyCollection keyCol = myDictionary.Keys; foreach (string key in keyCol/*string key in myDictionary.Keys*/) { Console.WriteLine("Key = {0}", key); }6、仅遍历值By Valus属性 Dictionary<string, int>.ValueCollection valueCol = myDictionary.Values; foreach (int value in valueCol) { Console.WriteLine("Value = {0}", value); }。
Java利⽤stream(流)对map中的values进⾏过滤、排序操作前⾔对于Java8中的stream(流)这种优雅、⽅便、快捷、⾼效的操作已经是信⼿沾来了吧,但是却仅限List、Set。
难道我Map不要⾯⼦得嘛?在⼯作中需要对从List转Map的数据进⾏操作,因此便有这随笔。
新建⼀个User类,注意下⾯使⽤lombok;如果你是idea请下载相关插件以及依赖,我这⾥使⽤maven引,在这⾥不多详细说明了。
/*** @program: strategy-demo* @description: stream操作* @author: YuAoTian* @create: 2020-01-06 23:23**/@Data@AllArgsConstructorclass User{private Integer id;private String name;private String city;private Integer age;}继续看代码,看Main⽅法⾥⾯的public static void main(String[] args) {List<User> userList = Arrays.asList(new User((int) (Math.random()*10),"⼩明","北京",18),new User((int) (Math.random()*10),"⼩红", "南京", 17),new User((int) (Math.random()*10),"⼩丫", "湖北", 14),new User((int) (Math.random()*10),"⼩⿊", "深圳", 22),new User((int) (Math.random()*10),"⼩⽟", "⼴州", 19),new User((int) (Math.random()*10),"⼩⼩", "江西", 21));Map<Integer, List<User>> userMap = userList.stream().collect(Collectors.groupingBy(User::getId));//已ID作为Key}Map排序正排Map<Integer, List<User>> map = userMap.entrySet().stream().sorted(paring(o -> o.getValue().get(0).getAge())).map(entry -> {Map<Integer, List<User>> result = new LinkedHashMap<>();result.put(entry.getKey(), entry.getValue());return result;}).reduce((map1, map2) -> {map2.forEach(map1::put);return map1;}).get();System.out.print(map);输出{5=[User(id=5, name=⼩丫, city=湖北, age=14), User(id=5, name=⼩⽟, city=⼴州, age=19), User(id=5, name=⼩⼩, city=江西, age=21)], 0=[User(id=0, name=⼩红, city=南京, age=17)], 8=[User(id=8, name=⼩明, city=北京, age=18)], 9=[User(id=倒排Map<Integer, List<User>> map = userMap.entrySet().stream().sorted(paring(o -> {//倒排中 reversed() ⽅法是object 对象,需要在⾥⾯强制回 Entry 就⾏。
Java中如何实现不可变Map详解前⾔有时最好不允许修改java.util.Map,例如跨线程共享只读数据。
为此,我们可以使⽤Unmodifiable Map或Immutable Map。
在这个快速教程中,我们将看到它们之间的区别。
然后,我们将介绍可以创建不可变Map的各种⽅法。
下⾯话不多说了,来⼀起看看详细的介绍吧不可修改与不可变Unmodifiable Map其实是⼀个可以修改的map的包装器,不允许直接修改它。
Map<String, String> mutableMap = new HashMap<>();mutableMap.put("USA", "North America");Map<String, String> unmodifiableMap = Collections.unmodifiableMap(mutableMap);assertThrows(UnsupportedOperationException.class,() -> unmodifiableMap.put("Canada", "North America"));但是包装器⾥⾯底层的可变Map仍然可以改变,修改也反映在不可修改的Map中:mutableMap.remove("USA");assertFalse(unmodifiableMap.containsKey("USA"));mutableMap.put("Mexico", "North America");assertTrue(unmodifiableMap.containsKey("Mexico"));另⼀⽅⾯,不可变Map包含其⾃⼰的私有数据,是不允许对其进⾏修改。
Java 实体类Bean 与Map 互相转化(两种⽅式)前⾔:实体类和map 相互转换,实体类需要有⽆参构造,不然会出现异常。
⼀:BeanUtils 类来实现pom:代码:<dependency ><groupId >commons-beanutils </groupId ><artifactId >commons-beanutils </artifactId ><version >1.8.0</version ><scope >compile </scope ></dependency ><dependency ><groupId >commons-logging </groupId ><artifactId >commons-logging </artifactId ><version >1.2</version ></dependency >package com.x;import java.util.HashMap;import java.util.Map;import mons.beanutils.BeanUtils;public class BeanTest {public static Map<String, Object> beanToMap(Object bean) {if (null == bean)return null ;try {Map <String, Object> map = BeanUtils.describe(bean);// 移除key=classmap.remove("class");System.out.println("JavaBean-->Map 转换前:" + bean.toString()); System.out.println("JavaBean-->Map 转换后:" + map);return map;} catch (Exception e) {System.out.println("JavaBean-->Map 转换失败:" + e.getMessage()); e.printStackTrace();return null ;}}public static <T> T mapToBean(Class<?> clazz, Map map) {try {T newBeanInstance = (T) clazz.newInstance();BeanUtils.populate(newBeanInstance, map);System.out.println("Map-->JavaBean 转换前:" + map);System.out.println("Map-->JavaBean 转换后:" + newBeanInstance.toString()); return newBeanInstance;} catch (Exception e) {System.out.println("Map-->JavaBean 转换失败:" + e.getMessage()); e.printStackTrace();return null ;}}public static void main(String[] args) {Map <String, Object> hashMap = new HashMap<>();hashMap.put("name", "谢辉");hashMap.put("age", 18);// map转实体类Xieh people = mapToBean(Xieh.class, hashMap);// 实体类转mapMap map = beanToMap(people);// 打印执⾏结果System.out.println(people.toString());System.out.println(map);}}⼆:jdk⾃带⽅法代码:package com.x2;import java.beans.BeanInfo;import java.beans.Introspector;import java.beans.PropertyDescriptor;import ng.reflect.Method;import java.util.HashMap;import java.util.Map;public class BeanTest {public static Map<String, Object> bean2Map(Object obj) {if (obj == null) {return null;}Map<String, Object> map = new HashMap<String, Object>();try {BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor property : propertyDescriptors) {String key = property.getName();// 过滤class属性if (!key.equals("class")) {// 得到property对应的getter⽅法Method getter = property.getReadMethod();Object value = getter.invoke(obj);map.put(key, value);}}} catch (Exception e) {e.printStackTrace();}return map;}public static Object mapToBean(Class type, Map map) {Object obj = null;try {BeanInfo beanInfo = Introspector.getBeanInfo(type);obj = type.newInstance();PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor descriptor : propertyDescriptors) {String propertyName = descriptor.getName();if (map.containsKey(propertyName)) {Object value = map.get(propertyName);descriptor.getWriteMethod().invoke(obj, value); }}} catch (Exception e) {System.out.println("map转实体类出现异常");}return obj;}public static void main(String[] args) {Xieh xieh = new Xieh();xieh.setName("谢辉");xieh.setAge(23);Map<String, Object> map = bean2Map(xieh);System.out.println(map.toString());Xieh object = (Xieh) mapToBean(Xieh.class, map);System.out.println(object.toString());}}测试实体类package com.x2;import java.io.Serializable;public class Xieh implements Serializable {private String name;private int age;public String getName() {return name;}public void setName(String name) { = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Xieh [name=" + name + ", age=" + age + "]";}}。
JAVA中JSONObject对象和Map对象之间的相互转换1.由json字符串转换成Map对象如json字符串:{"contend":[{"bid":"22","carid":"0"},{"bid":"22","carid":"0"}],"result":100,"total":2}下⾯直接附代码://json字符串String jsondata="{\"contend\":[{\"bid\":\"22\",\"carid\":\"0\"},{\"bid\":\"22\",\"carid\":\"0\"}],\"result\":100,\"total\":2}";JSONObject obj= JSON.parseObject(jsondata);//map对象Map<String, Object> data =new HashMap<>();//循环转换Iterator it =obj.entrySet().iterator();while (it.hasNext()) {Map.Entry<String, Object> entry = (Entry<String, Object>) it.next();data.put(entry.getKey(), entry.getValue());}System.out.println("map对象:"+data.toString());下⾯是输出内容:{total=2, contend=[{"carid":"0","bid":"22"},{"carid":"0","bid":"22"}], result=100}2.由Map对象转换成json字符串//map对象Map<String, Object> data =new HashMap<>();String x =JSONObject.toJSONString(data);System.out.println("json字符串:"+x);下⾯是输出内容:{"total":2,"result":100,"contend":[{"carid":"0","bid":"22"},{"carid":"0","bid":"22"}]}到此这篇关于JAVA中JSONObject对象和Map对象之间的相互转换的⽂章就介绍到这了,更多相关JAVA JSONObject和Map相互转换内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
【Java必修课】各种集合类的合并(数组、List、Set、Map)1 介绍集合类可谓是学习必知、编程必⽤、⾯试必会的,⽽且集合的操作⼗分重要;本⽂主要讲解如何合并集合类,如合并两个数组,合并两个List等。
通过例⼦讲解⼏种不同的⽅法,有JDK原⽣的⽅法,还有使⽤第三库的⽅法。
2 第三⽅库引⼊⼗分常⽤的优秀的第三⽅库Guava和Apache Commons;通过配置pom.xml如下:<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>28.1-jre</version></dependency><dependency><groupId>mons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version></dependency><dependency><groupId>mons</groupId><artifactId>commons-exec</artifactId><version>1.3</version></dependency><dependency><groupId>mons</groupId><artifactId>commons-lang3</artifactId><version>3.5</version></dependency>最新版本可以去官⽹搜索查看。
Java中List与Map初始化的⼀些写法Java的在还没有发现新写法之前时,我⼀直是这么初始化List跟Map:代码如下复制代码//初始化ListList<string> list = new ArrayList</string><string>();list.add();list.add("string2");//some other list.add() code......list.add("stringN");//初始化MapMap</string><string , String> map = new HashMap</string><string , String>();map.put("key1", "value1");map.put("key2", "value2");//.... some other map.put() codemap.put("keyN", "valueN");</string>好⿇烦啊。
有⼀天撸到这样的⼀种⽅式:代码如下复制代码//初始化ListList<string> list = new ArrayList</string><string>(){{add("string1");add("string2");//some other add() code......add("stringN");}};//初始化MapMap</string><string , String> map = new HashMap</string><string , String>(){{put("key1", "value1");put("key2", "");//.... some other put() codeput("keyN", "valueN");}};</string>虽然看起来没少写多少代码,但是个⼈觉得这种⽅式还是简洁多了很多,很流畅啊哈哈~例,后现⼀聚⼩编测试了List两个实例更简单法⼀:利⽤Array与ArrayList的相互转换⽅法,代码如下:代码如下复制代码ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));法⼆:利⽤ArrayList的add⽅法完成初始化赋值,代码如下:代码如下复制代码List list = new ArrayList<String>(){{add("A");add("B");}}更多详细内容请查看:。
keyset 方法在Java中,KeySet方法是一种用于获取Map中所有键的集合的方法。
在本文中,我们将详细介绍KeySet方法的使用和作用。
首先,让我们来了解一下Map。
Map是Java中的一种接口,它存储着键值对的集合。
在Map中,每个键都是唯一的,而值可以重复。
常用的Map实现类包括HashMap、TreeMap和LinkedHashMap等。
KeySet方法的作用是返回一个包含Map中所有键的Set集合。
通过KeySet方法,我们可以轻松地获取Map中所有的键,然后进行遍历、查找或其他操作。
接下来,让我们看一下KeySet方法的语法:```java。
Set<K> keySet()。
```。
其中,K表示键的类型。
KeySet方法没有参数,它会返回一个包含Map中所有键的Set集合。
下面是一个简单的示例,演示了如何使用KeySet方法:```java。
Map<String, Integer> map = new HashMap<>();map.put("A", 1);map.put("B", 2);map.put("C", 3);Set<String> keySet = map.keySet();for (String key : keySet) {。
System.out.println(key + ": " + map.get(key));}。
```。
在这个示例中,我们首先创建了一个HashMap对象,并向其中添加了三组键值对。
然后,我们调用KeySet方法获取Map中所有的键,并将其存储在名为keySet的Set集合中。
最后,我们使用for循环遍历keySet,获取每个键对应的值,并将其打印出来。
除了遍历键值对,KeySet方法还可以用于其他操作,比如判断某个键是否存在于Map中:```java。
java类转map方法Java是一种面向对象的编程语言,它具有强大的类和对象的概念。
在Java中,类是用于创建对象的蓝图,而对象是类的实例。
在开发过程中,经常会遇到将Java类转换为Map的需求,本文将介绍如何实现这一功能。
让我们来看一下Java中的类和对象是如何定义的。
在Java中,我们可以通过关键字"class"来定义一个类,然后在类中定义属性和方法。
属性是类的特征,而方法是类的行为。
当我们创建一个对象时,实际上就是创建了该类的一个实例,我们可以通过对象来访问类中定义的属性和方法。
要将Java类转换为Map,我们首先需要了解Map的概念。
在Java 中,Map是一种键值对的数据结构,它可以存储不重复的键和对应的值。
在Map中,键是唯一的,而值可以重复。
Map提供了一系列方法来操作键值对,比如添加、删除、查找等。
接下来,我们将介绍如何将Java类转换为Map。
首先,我们需要创建一个空的Map对象,可以使用HashMap或者LinkedHashMap等实现类来实例化一个Map对象。
然后,我们需要获取类的属性和对应的值,可以使用Java反射机制来实现。
通过反射,我们可以获取类的所有属性,并通过get方法获取属性的值。
然后,将属性名作为键,属性值作为值,添加到Map中。
下面是将Java类转换为Map的示例代码:```javapublic class MyClass {private String name;private int age;public MyClass(String name, int age) { = name;this.age = age;}// getter and setter methodspublic static void main(String[] args) {MyClass myClass = new MyClass("张三", 20); Map<String, Object> map = new HashMap<>(); Class<?> clazz = myClass.getClass();Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) {field.setAccessible(true);try {Object value = field.get(myClass);map.put(field.getName(), value);} catch (IllegalAccessException e) {e.printStackTrace();}}System.out.println(map);}}```在上面的示例代码中,我们定义了一个名为MyClass的类,该类具有name和age两个属性。
java map key规则全文共四篇示例,供读者参考第一篇示例:Java中的Map是一种存储键值对的数据结构,其中每个键都是唯一的。
在使用Map时,对于Key的选择是非常重要的,因为它直接影响到程序的性能和正确性。
在这里我们将讨论一些关于Java Map Key 规则的重要注意事项。
1. Key的唯一性在Java的Map中,每个键都必须是唯一的。
如果向Map中添加了一个已经存在的键值对,那么新的值将会覆盖旧的值。
这意味着在选择Key时应该确保其唯一性,否则可能会导致数据的混乱和不确定性。
2. Key的不可变性在Java中,字符串、基本数据类型(如Integer、Double等)、枚举和不可变对象(如Java中的日期对象)通常作为Map的Key,因为它们是不可变的,一旦创建就不会发生改变。
这确保了Key的稳定性,避免了可能导致Map不一致的问题。
3. 自定义对象作为Key虽然Java提供了一些已有的类作为Map的Key,但有时候我们可能需要使用自定义对象作为Key。
在这种情况下,需要确保自定义对象重写了equals()和hashCode()方法。
equals()方法用于比较两个对象是否相等,而hashCode()方法用于返回对象的哈希码值,这样可以保证Key的唯一性和一致性。
4. 选择合适的哈希函数在Java中,HashMap是最常用的Map实现类之一,它使用哈希表来存储键值对。
在选择Key时,应考虑选择合适的哈希函数,以确保散列的均匀性和快速的查找速度。
如果使用自定义对象作为Key,还需要重写hashCode()方法以生成适当的哈希码值。
5. 谨慎选择可变对象作为Key虽然在Java中可以使用可变对象作为Map的Key,但这可能会导致一些潜在的问题。
如果可变对象发生了改变,其哈希码值也会发生变化,这可能导致Map无法正确查找到对应的值。
应尽量避免使用可变对象作为Key,或者在使用时保证不会修改它们。
java8中stream的map和flatmap的理解假如我们有这样⼀个需求给定单词列表["Hello","World"],你想要返回列表["H","e","l", "o","W","r","d"],对于这样的需求,我们可能想到的第⼀个版本可能是这样⼦的:words.stream().map(word -> word.split("")).distinct().collect(toList());这个⽅法的问题在于,传递给map⽅法的Lambda为每个单词返回了⼀个String[](String列表)。
因此, map 返回的流实际上是Stream<String[]> 类型的。
你真正想要的是⽤Stream<String>来表⽰⼀个字符流。
因此,这是⾏不通的。
以下是我对这个问题的解法和分步写法,希望能对你有帮助:对flatMap的说明:这个在这⾥的主要作⽤是对流进⾏扁平化String ss = "Hello";23 String[] aa = ss.split("");45 String[] bb = {"H", "e", "l", "l", "o"};678 String[] strings = {"Hello", "World"};910//Arrays.stream接收⼀个数组返回⼀个流11 List<Stream<String>> streamList = Arrays.asList(strings).stream().12 map(str -> str.split("")).13 map(str -> Arrays.stream(str)).14 collect(Collectors.toList());1516//分步写(map)1718 Stream<String[]> stream = Arrays.asList(strings).stream().19 map(str -> str.split(""));2021 Stream<Stream<String>> streamStream = stream.map(strings1 -> Arrays.stream(strings1));22 List<Stream<String>> streamList1 = streamStream.collect(Collectors.toList());232425 List<String> stringList = Arrays.asList(strings).stream().26 map(str -> str.split("")).27 flatMap(str -> Arrays.stream(str))28 .collect(Collectors.toList());293031//分步写(流只能消费⼀次)(flatMap)32 Stream<String[]> stream1 = Arrays.asList(strings).stream().33 map(str -> str.split(""));3435 Stream<String> stringStream = stream1.flatMap(strings1 -> Arrays.stream(strings1));3637 List<String> stringList1 = stringStream.collect(Collectors.toList());1.map将⼀种类型的值转换为另外⼀种类型的值。
java中Map类Map以按键/数值对的形式存储数据,和数组非常相似,在数组中存在的索引,它们本身也是对象。
Map的接口Map---实现MapMap.Entry--Map的内部类,描述Map中的按键/数值对。
SortedMap---扩展Map,使按键保持升序排列关于怎么使用,一般是选择Map的子类,而不直接用Map类。
下面以HashMap为例。
public static void main(String args[]){HashMap hashmap = new HashMap();hashmap.put("Item0", "Value0");hashmap.put("Item1", "Value1");hashmap.put("Item2", "Value2");hashmap.put("Item3", "Value3");Set set = hashmap.entrySet();Iterator iterator = set.iterator();while (iterator.hasNext(){Map.Entry mapentry = (Map.Entry) iterator.next();System.out.println(mapentry.getkey() + "/" + mapentry.getValue());}}注意,这里Map的按键必须是唯一的,比如说不能有两个按键都为null。
如果用过它,就会知道它的用处了。
又比如:Map<String, Order> map = new HashMap<String, Order>();map.put("Order", (Order) obj);资料:Collection容器中包含Set和List接口,Set中又包含HashSet,List中包含LinkedList和ArrayList;单独的Map接口中只有HashMap。
java.util 中的集合类包含Java 中某些最常用的类。
最常用的集合类是List 和Map。
List 的具体实现包括ArrayList 和Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。
List 适用于按数值索引访问元素的情形,其中的数据有顺序且可以重复。
而Set中数据无顺序且不可以重复。
Map 提供了一个更通用的元素存储方法。
Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。
从概念上而言,您可以将List 看作是具有数值键的Map。
而实际上,除了List 和Map 都在定义java.util 中外,两者并没有直接的联系。
本文将着重介绍核心Java 发行套件中附带的Map,同时还将介绍如何采用或实现更适用于您应用程序特定数据的专用Map。
了解Map 接口和方法Java 核心类中有很多预定义的Map 类。
在介绍具体实现之前,我们先介绍一下Map 接口本身,以便了解所有实现的共同点。
Map 接口定义了四种类型的方法,每个Map 都包含这些方法。
下面,我们从两个普通的方法(表1)开始对这些方法加以介绍。
表1:覆盖的方法。
我们将这Object 的这两个方法覆盖,以正确比较Map 对象的等价性。
equals(Object o) 比较指定对象与此Map 的等价性hashCode() 返回此Map 的哈希码Map 构建Map 定义了几个用于插入和删除元素的变换方法(表2)。
表2:Map 更新方法:可以更改Map 内容。
clear() 从Map 中删除所有映射remove(Object key) 从Map 中删除键和关联的值put(Object key, Object value) 将指定值与指定键相关联clear() 从Map 中删除所有映射putAll(Map t) 将指定Map 中的所有映射复制到此map尽管您可能注意到,纵然假设忽略构建一个需要传递给putAll() 的Map 的开销,使用putAll() 通常也并不比使用大量的put() 调用更有效率,但putAll() 的存在一点也不稀奇。
这是因为,putAll() 除了迭代put() 所执行的将每个键值对添加到Map 的算法以外,还需要迭代所传递的Map 的元素。
但应注意,putAll() 在添加所有元素之前可以正确调整Map 的大小,因此如果您未亲自调整Map 的大小(我们将对此进行简单介绍),则putAll() 可能比预期的更有效。
查看Map迭代Map 中的元素不存在直接了当的方法。
如果要查询某个Map 以了解其哪些元素满足特定查询,或如果要迭代其所有元素(无论原因如何),则您首先需要获取该Map 的“视图”。
有三种可能的视图(参见表3)所有键值对—参见entrySet()所有键—参见keySet()所有值—参见values()前两个视图均返回Set 对象,第三个视图返回Collection 对象。
就这两种情况而言,问题到这里并没有结束,这是因为您无法直接迭代Collection 对象或Set 对象。
要进行迭代,您必须获得一个Iterator 对象。
因此,要迭代Map 的元素,必须进行比较烦琐的编码Iterator keyValuePairs = aMap.entrySet().iterator();Iterator keys = aMap.keySet().iterator();Iterator values = aMap.values().iterator();值得注意的是,这些对象(Set、Collection 和Iterator)实际上是基础Map 的视图,而不是包含所有元素的副本。
这使它们的使用效率很高。
另一方面,Collection 或Set 对象的toArray() 方法却创建包含Map 所有元素的数组对象,因此除了确实需要使用数组中元素的情形外,其效率并不高。
我运行了一个小测试(随附文件中的Test1),该测试使用了HashMap,并使用以下两种方法对迭代Map 元素的开销进行了比较:Profilers in Oracle JDeveloperOracle JDeveloper 包含一个嵌入的监测器,它测量内存和执行时间,使您能够快速识别代码中的瓶颈。
我曾使用Jdeveloper 的执行监测器监测HashMap 的containsKey() 和containsValue() 方法,并很快发现containsKey() 方法的速度比containsValue() 方法慢很多(实际上要慢几个数量级!)。
(参见图 1 和图2,以及随附文件中的Test2 类)。
int mapsize = aMap.size();Iterator keyValuePairs1 = aMap.entrySet().iterator();for (int i = 0; i < mapsize; i++){ Map.Entry entry = (Map.Entry) keyValuePairs1.next(); Object key =entry.getKey(); Object value = entry.getValue(); ...}Object[] keyValuePairs2 =aMap.entrySet().toArray();for (int i = 0; i < rem; i++) {{ Map.Entry entry = (Map.Entry)keyValuePairs2[i]; Object key = entry.getKey();Profilers in Oracle JDeveloperOracle JDeveloper 包含一个嵌入的监测器,它测量内存和执行时间,使您能够快速识别代码中的瓶颈。
我曾使用Jdeveloper 的执行监测器监测HashMap 的containsKey() 和containsValue() 方法,并很快发现containsKey() 方法的速度比containsValue() 方法慢很多(实际上要慢几个数量级!)。
(参见图 1 和图2,以及随附文件中的Test2 类)。
Object value = entry.getValue(); ...}此测试使用了两种测量方法:一种是测量迭代元素的时间,另一种测量使用toArray 调用创建数组的其他开销。
第一种方法(忽略创建数组所需的时间)表明,使用已从toArray 调用中创建的数组迭代元素的速度要比使用Iterator 的速度大约快30%-60%。
但如果将使用toArray 方法创建数组的开销包含在内,则使用Iterator 实际上要快10%-20%。
因此,如果由于某种原因要创建一个集合元素的数组而非迭代这些元素,则应使用该数组迭代元素。
但如果您不需要此中间数组,则不要创建它,而是使用Iterator 迭代元素。
表3:返回视图的Map 方法:使用这些方法返回的对象,您可以遍历Map 的元素,还可以删除Map 中的元素。
entrySet() 返回Map 中所包含映射的Set 视图。
Set 中的每个元素都是一个Map.Entry 对象,可以使用getKey() 和getValue() 方法(还有一个setValue() 方法)访问后者的键元素和值元素keySet() 返回Map 中所包含键的Set 视图。
删除Set 中的元素还将删除Map 中相应的映射(键和值)values() 返回map 中所包含值的Collection 视图。
删除Collection 中的元素还将删除Map 中相应的映射(键和值)访问元素表 4 中列出了Map 访问方法。
Map 通常适合按键(而非按值)进行访问。
Map 定义中没有规定这肯定是真的,但通常您可以期望这是真的。
例如,您可以期望containsKey() 方法与get() 方法一样快。
另一方面,containsValue() 方法很可能需要扫描Map 中的值,因此它的速度可能比较慢。
表4:Map 访问和测试方法:这些方法检索有关Map 内容的信息但不更改Map 内容。
get(Object key) 返回与指定键关联的值containsKey(Object key) 如果Map 包含指定键的映射,则返回truecontainsValue(Object value) 如果此Map 将一个或多个键映射到指定值,则返回trueisEmpty() 如果Map 不包含键-值映射,则返回truesize() 返回Map 中的键-值映射的数目对使用containsKey() 和containsValue() 遍历HashMap 中所有元素所需时间的测试表明,containsValue() 所需的时间要长很多。