如何用Map对象创建Set对象
来源:互联网 发布:数学院士知乎 编辑:程序博客网 时间:2024/04/30 14:14
Java中的Map和Set有不少相似之处。本文将分享一个把Map类转化成Set类的小技巧。
或许你已经知道,HashSet其实是一个披着Set方法外衣的HashMap;同样,TreeSet其实也是一个披着Set方法外衣的TreeMap。Map并不支持直接用迭代器进行遍历,因此下面的这段代码编译无法通过:
Map<String, Double> salaries =
new
HashMap<>();
for
(
double
salary : salaries) {
// does not compile
}
我们可以通过遍历Map中的key集合、value集合和entry集合来实现Map的遍历。由于Map中的value是可以重复出现的,因此values()方法返回的是一个Collection类型的集合。而Map中的key是不允许重复的,因此keySet()方法和entrySet()返回的都是Set类型的集合。
因此,我们可以采用下面的方法来遍历Map:
Map<String, Double> salaries =
new
HashMap<>();
for
(
double
salary : salaries.values()) {
}
或者可以通过遍历key来遍历Map:
Map<String, Double> salaries =
new
HashMap<>();
for
(String name : salaries.keySet()) {
}
当然,还可以通过遍历entry来遍历Map:
Map<String, Double> salaries =
new
HashMap<>();
for
(Map.Entry<String, Double> entry : salaries.entrySet()) {
String name = entry.getKey();
double
salary = entry.getValue();
}
我经常看到程序员这样遍历Map:先获取keySet,然后对keys进行遍历,并通过get()方法找到对应的value。
Map<String, Double> salaries =
new
HashMap<>();
for
(String name : salaries.keySet()) {
// less efficient way to
double
salary = salaries.get(name);
// iterate over entries
}
从直观上看,采用遍历entry的方式遍历Map会更加高效一些,这种遍历方式的时间复杂度是O(n)。然而,如果HashMap中的元素分布均匀,调用get()方法查找元素的时间复杂度将是O(1),那么这两种方法遍历HashMap的时间复杂度是一样的,都是O(n)。这两种遍历方式虽然有所不同,但时间复杂度都是线性的。但这个结论并不适用于其它类型的Map,特别是TreeMap。TreeMap的平均查找效率是O(log n),因此通过keySet遍历TreeMap的时间复杂度是O(n x log n)。
java.util包中有很多Map类,其中一些Map类有着对应类型的Set类实现,例如TreeMap和HashMap。这些Set类都是基于对应的Map类实现的,因此它们和对应的Map类保持相同的算法复杂度以及并发特性。
本文的重点来了。我在完成并发专修课程中的某道练习题时,需要一个快速高效并且线程安全的HashSet。起初,我直接把ConcurrentHashMap当作Set用,把要插入Set的元素以Key的形式插入Map,Key所对应的Value则是一个无意义的默认值。后来我发现,Java 6中的java.util.Collections类提供了一个newSetFromMap()方法,该方法能够基于指定的Map对象创建一个新的Set对象。在创建这个Map<K, V>对象时,K的数据类型必须与你想要创建的Set中元素的数据类型一致;而V必须是Boolean类型的,这是因为value字段用于标记该元素是否存在。
import
java.util.*;
import
java.util.concurrent.*;
public
class
ConcurrentSetTest {
public
static
void
main(String[] args) {
Set<String> names = Collections.newSetFromMap(
new
ConcurrentHashMap<String, Boolean>()
);
names.add(
"Brian Goetz"
);
names.add(
"Victor Grazi"
);
names.add(
"Heinz Kabutz"
);
names.add(
"Brian Goetz"
);
System.out.println(
"names = "
+ names);
}
}
当然,newSetFromMap()方法只能返回标准Set接口类型的对象。如果你的Map类有着更丰富的接口(与标准Map<K, V>接口相比),你还是需要自行封装实现对应的Set类。
希望读者能从本文中有所收获。如果你曾经为找不到ConcurrentHashSet而烦恼,现在你就可以自己创建一个了。
- 如何用Map对象创建Set对象
- 如何用JAVA 对象?
- 如何用Revit API从无到有创建构建的类型对象?
- ultrawebgird如何用rowId得到row 对象
- 如何用eval来获取对象
- 如何用C语言实现面向对象
- SpringMVC如何用实体对象接收参数
- Js实现Map对象,set对象
- 如何用创建命名对象来判断应用程序是否已有一个实例在运行?
- Map集合的实例对象中创建对象。然后通过Set集合获取
- JavaScript构造创建Map对象
- java, set,map,table,LinkedList 对象仓库
- List,Map,Set,对象数组(VO中)
- spring如何注入List,Set,Map对象
- java对象容器List,Map,Set
- Map json list set 对象之间转换
- 如何用JAVA实现在ACCESS表中插入对象?
- 如何用数据表对象生成 sql insert 命令
- 电力企业的大数据时代
- 【脚本】shell 截取字符串的方法*
- 第20章 WWW服务器
- git常用
- 大数据在电力行业的应用前景有哪些?
- 如何用Map对象创建Set对象
- 【脚本】Shell 获取全路径的目录和文件名*
- SQL的decimal、float、double类型的区别
- 从“迈克尔·克莱顿”的《机身》说开去——质量管理,良币如何驱逐劣币
- SQL Server日志清空方法
- 《大话操作系统——做坚实的工程实践派》(4)
- vmware加速方法总结
- 精 挑 细 选
- 单链表的实现