在《Java集合Collection简介及List与Map使用示例》我们介绍了集合的基本使用。本节介绍如何在定义时就初始化集合。
Collection
有时,需要集合在定义时就要初始化(特别是定义集合常量时)。
传统方式
Collection有两种常用的初始化方式:
- 构造器方式:通过接受另外一个Collection来初始化集合;
- add方式:静态变量可通过static块;
private static final Map<String, Integer> mapTest = new HashMap<>();
static {
mapTest.add("one", 1);
mapTest.add("two", 2);
}
双括号方式
双大括号初始化(double brace initialization)或者匿名内部类初始化法:第一层括号定义了一个内部匿名类(实际类型的子类);第二次括号则为匿名类实例的初始化代码。
List<Integer> lstTest = Arrays.asList(1, 3, 5, 7);
// 通过构造器初始化
Collection<Integer> colTest = new HashSet<>(lstTest);
// 通过add方法初始化
Set<Integer> setTest = new HashSet<Integer>() {
{
addAll(lstTest);
add(2);
add(4);
}
};
利用双大括号初始化集合使代码简洁,但是也存在一些问题:
- 从效率上来说可能不如标准的集合初始化步骤:原因在于使用双大括号初始化会导致内部类文件的产生,而这个过程就会影响代码的执行效率。
- 串行化时可能存在问题:
Arrays.asList
List除通过上述方式外,也可通过Arrays.asList方便地通过把数字转换为List(此方式生成的List是不可修改的)。
List<Integer> lstTest = Arrays.asList(1, 3, 5, 7);
要生成ArrayList,可通过Guava中的Lists.newArrayList、或Stream.of来生成:
List<Integer> lstOne = Lists.newArrayList(1, 2, 3); // ArrayList
List<Integer> lstTwo = Stream.of(1, 2, 3).collect(Collectors.toList()); // ArrayList
List<Integer> lstThree = Arrays.asList(1, 2, 3); // Arrays$ArrayList
Map
初始化示例
以一个value为BiFunction为例说明:当内部由Lambd表达式时,HashMap必须指明类型(否则可以直接用<>,让编译器自动推导)。
static{
BiFunction<String, String, String> funOne = (n, p) -> {
return checkNameOne(n, p);
};
Map<Integer, BiFunction<String, String, String>> mapFun = new HashMap<Integer, BiFunction<String, String, String>>() {{
put(1, funOne);
put(2, (n, p) -> checkNameTwo(n, p));
}};
}
static String checkNameOne(String name, String phone) {
return "One";
}
static String checkNameTwo(String name, String phone) {
return "Two";
}
Stream流
Map中有三类流:键、值与键值对流;
Map<String, Integer> mapTest = new HashMap<String, Integer>() {{
put("one", 1);
put("two", 2);
put("three", 3);
}};
mapTest.values().stream()
.collect(Collectors.toSet());
mapTest.keySet().stream()
.count();
mapTest.entrySet().stream()
.forEach((e) -> System.out.println(e.getKey() + "=" + e.getValue()));
compute
map中可通过compute类函数方便地处理键值:通过接受一个BiFunction参数(参数为原来的key与value,返回新的value),可以对已有与新的value进行计算操作:
- compute:键不存在时,value为null;
- computeIfAbsent:键不存在时有效(参数为Function);
- computeIfPresent:键存在时有效;
Map<String, Integer> mapCount = new HashMap<>();
for (int i = 0; i < 10; ++i) {
Integer rand = RandomHelper.randInt(10);
mapCount.compute(rand.toString(), (k, v) ->
v == null ? rand : rand + v
);
}
merge
merge与compute类似,但是其BiFunction参数为新、旧Value;
Map<String, Integer> mapCount = new HashMap<>();
for (int i = 0; i < 20; ++i) {
// Integer rand = RandomHelper.randInt(10);
// mapCount.compute(rand.toString(), (k, v) ->
// v == null ? rand : rand + v
// );
mapCount.merge(rand.toString(), rand, (oldV, newV) ->
oldV == null ? newV : oldV + newV
);
}