Java8、9中的Collection API的增强功能
1.集合工厂
使用java创建由少量元素构成的列表
ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("b");
不过这种方法比较low,而且代码很多。
更加简洁的方式是 Arrays.asList()的方法,不过通过此方法,创建的是一个固定大小的列表,列表的元素可以更新,但是不能增加或者删除,否则会报错。
那Set集合也有对应的工厂方法吗?我们并没有发现有这种Arrays.asSet()类似的方法,不过我们可以通过Set的构造方法创建。
Set<String> set = new HashSet<>(Arrays.asList("a","b"));
不过通过此方法创建的是可变的Set。
Map呢,目前没有发现可以优雅创建小规模的map,不过java9新引入的工厂方法,可以小规模创建List,set,Map。
1.1 List工厂
List.of()方法
我们发现List接口中有多个of()的重载方法
并且创建的是一个只读的list,不能新增,修改和删除,否则报错。
1.2 Set工厂
同理,set中也存在of()方法,并且创建的是不可变的Set集合 。并且如果of的参数列表中存在相同元素会报错。
1.3 Map工厂
与创建List和Set相比,创建Map稍微复杂一点。
工厂方法:Map.of(),该方法交替地以列表中地元素作为键和值。
Map.ofEntries()方法,接收以变长参数列表形式组织地Map.Entry<k,v>对象作为参数。
2.使用List和Set
2.1 removeIf方法
有时候我们需要按照指定条件移除List中的元素,如下代码:
@Test public void test(){ List<User> users = new ArrayList<>(); users.add(new User("a",20)); users.add(new User("b",18)); users.add(new User("b",17)); for(User user : users){ if(user.getAge()>=18){ users.remove(user); } } System.out.println(users); }
但是,很遗憾,会报异常,是因为增强for循环底层使用的是iterator迭代器,通过List.remove()方法操作集合后,迭代器对象的状态没有与集合对象的状态同步,我们需要改成iterator.remove()去修改集合。
但是java8以后,通过removeIf方法,就可以避免上述缺陷。
users.removeIf(u->u.getAge()>=18);
2.2 replaceAll方法
List接口中提供的replaceAll方法让我们可以使用一个新的元素去替换列表中满足要求的每个元素。
@Test public void test2(){ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); list.replaceAll(a-> a>3 ? a+1 : a-1); System.out.println(list); }
3.使用Map
3.1 forEach方法
一直以来,遍历Map一直都很麻烦,使用Map.Entry<K,V>迭代器遍历或者使用map.keySet对键进行遍历。
从java8开始,Map接口中提供了forEach的默认方法,该方法接收一个BiConsumer,以键和值作为参数。
@Test public void test3(){ Map<Integer ,User> userMap = new HashMap<>(); userMap.put(1,new User("a",20)); userMap.forEach((k,v)-> System.out.println(k+":"+v)); }
3.2 排序
有两种新的工具可以对Map的键或值排序
Entry.comparingByValue 和 Entry.comparingByKey
@Test public void test4(){ Map<Integer ,User> userMap = new HashMap<>(); userMap.put(1,new User("a",20)); userMap.put(2,new User("a",18)); userMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.comparing(User::getAge))).forEach(System.out::println); }
Map<Integer ,User> userMap = new HashMap<>(); userMap.put(1,new User("a",20)); userMap.put(2,new User("b",18)); userMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(System.out::println);
3.3 getOrDefualt()方法
如果我们查找的键在Map中不存在时,会收到一个null,在程序中可能会造成空指针异常。
使用getOrDefault方法,接收第一个参数作为键,第二个参数作为默认值。当键在map中找不到时,会将这个默认值返回。
Map<Integer ,User> userMap = new HashMap<>(); userMap.put(1,new User("a",20)); userMap.put(2,new User("b",18)); User user = userMap.getOrDefault(3,new User("c",22)); System.out.println(user);
3.4 计算模式
有时,我们希望依据键在Map中存在或者缺失的情况,有条件地执行某个操作,并存储计算的结果
computeIfAbset:如果指定的键没有对应的值(没有改键或者键对应的值为空),那么使用该键计算新的值,并添加到Map中。
computeIfPresent:如果指定的键在Map中存在,就计算该键的新值,并添加到Map中。
compute:使用指定的键计算新的值,并添加到Map中。
3.5 删除模式
java8以前的Map中的remove,只能根据指定的key去删除映射。
java8中提供了重载的remove放啊,可以删除指定的键值对。
default boolean remove(Object key, Object value) { Object curValue = get(key); if (!Objects.equals(curValue, value) || (curValue == null && !containsKey(key))) { return false; } remove(key); return true; }
3.6 替换模式
replaceAll:通过BiFunction替换map中每一个项的值。
public void test6(){
HashMap<String, String> map = new HashMap<>();
map.put("1","blue");
map.put("2","red");
map.replaceAll((num,color)->color.toUpperCase());
map.forEach((x,y)->{
System.out.println(x+y);
});
}