天天看点

JDK1.8特性整理

接口默认方法

在Java中只有单继承,如果要让一个类赋予新的特性,通常是使用接口来实现,允许一个子类同时具有多个父类的接口与功能。

接口中用default关键字实现默认方法

Lambda表达式

是一个匿名函数,即没有函数名的函数

内建函数接口

  • Predicate接口:Predicate 接口只有一个参数,返回boolean类型。
Predicate<String> predicate = (s) -> s.length() > 0;
predicate.test("ziyuan");              // true
predicate.negate().test("ziyuan");     // false
Predicate<String> isEmpty = String::isEmpty;
isEmpty.test("ziyuan");
Predicate<String> isNotEmpty = isEmpty.negate();
           
  • Function 接口:Function 接口有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen)
Function<Integer, Integer> doubled = e -> e * 2;
 Function<Integer, Integer> squared = e -> e * e;
 //compose(before)
 doubled.compose(squared).apply(4); //32
 //andThen(after) 
 doubled.andThen(squared).apply(4); //64
           
  • Supplier 接口:Supplier 接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数
Supplier<Person> personSupplier = Person::new;
personSupplier.get();  
           
  • Consumer 接口:Consumer 接口表示执行在单个参数上的操作。
Consumer<String> consumer = (s) -> System.out.println("Hello, " + s.charAt(0));
 String res = consumer.accept("ziyuan");
           
  • Comparator 接口:Comparator 是老Java中的经典接口,增加了默认方法
Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);

Person p1 = new Person("xin", "wang");
Person p2 = new Person("bai", "xue");
comparator.compare(p1, p2);             // > 0
comparator.reversed().compare(p1, p2);  // < 0
           
  • Optional 接口:
Optional.ofNullable(sign.getProxyShopId()).orElse(SysConstants.NONE);
mktMaterialVO.setGoodsId(Optional.ofNullable(mktMaterialVO.getGoodsId()).orElse(0L));
Optional.ofNullable(memberVO.getShopVO().getShopInfoVO().getSupId()).orElse(SysConstants.NONE);

// old coding
String isocode = "";
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            if (isocode != null) {
                isocode = isocode.toUpperCase();
            }
        }
    }
}
//new coding
String isocode = Optional.ofNullable(user.getAddress().getCountry().getIsocode().toUpperCase()).orElse("");
           
Stream : Collection.stream() 或者 Collection.parallelStream() 来创建一个Stream
java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行执行或者并行执行。
  • foreach:循环,是一个最终操作
billItemVOList.stream().forEach(billItemVO -> billItemVO.setBillId(biDynaFormBillVO.getId()));
           
  • Filter 过滤:通过一个predicate接口来过滤并只保留符合条件的元素
List<AppPageVO> appPageVOList = 
        appPageVOS
        .stream()
        .filter(appPageVO -> idList.contains(appPageVO.getId()))
        .collect(Collectors.toList());
           
  • Sort 排序:排序是一个中间操作,返回的是排序好后的Stream。如果你不指定一个自定义的Comparator则会使用默认排序。
List<String> stringCollection = new ArrayList<>();
stringCollection.add("dba");
stringCollection.add("abc");
stringCollection.add("bcd");
stringCollection.add("cba");
stringCollection.add("dbc");
stringCollection
    .stream()
    .sorted()
    //.filter((s) -> s.startsWith("a"))
    .collect(Collectors.toList())
    .forEach(System.out::println); //abc bcd cba dba dbc

           
排序只创建了一个排列好后的Stream,而不会影响原有的数据源,排序之后原数据stringCollection是不会被修改的。
  • Map 映射:中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,下面的示例展示了将字符串转换为大写字符串。你也可以通过map来讲对象转换成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的。
List<Long> isBIdList = subordinateMemberList.stream().filter(vo ->
                    vo.getMemberLevelVO() != null && vo.getMemberLevelVO().getIsB() == SysConstants.YES
            ).map(MemberBO::getId).collect(Collectors.toList());
            
stringCollection
    .stream()
    .map(String::toUpperCase)
    .sorted((a, b) -> b.compareTo(a))
    .forEach(System.out::println);
           
  • Match 匹配:Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作,并返回一个boolean类型的值。
boolean anyStartsWithA = 
    stringCollection
        .stream()
        .anyMatch((s) -> s.startsWith("a"));
System.out.println(anyStartsWithA);      // true

boolean allStartsWithA = 
    stringCollection
        .stream()
        .allMatch((s) -> s.startsWith("a"));
System.out.println(allStartsWithA);      // false

boolean noneStartsWithZ = 
    stringCollection
        .stream()
        .noneMatch((s) -> s.startsWith("z"));
System.out.println(noneStartsWithZ);      // true
           
  • Count 计数 :计数是一个最终操作,返回Stream中元素的个数,返回值类型是long。
long startsWithB = 
    stringCollection
        .stream()
        .filter((s) -> s.startsWith("b"))
        .count();
System.out.println(startsWithB);    // 1
           
  • Reduce 规约:这是一个最终操作,允许通过指定的函数来将stream中的多个元素规约为一个元素,规越后的结果是通过Optional接口表示的:
Optional<String> reduced =
    stringCollection
        .stream()
        .sorted()
        .reduce((s1, s2) -> s1 + "#" + s2);

reduced.ifPresent(System.out::println);
// abc#bcd#cba#dba#dbc
           
  • 并行Streams :
List<Long> idList = shopGoodsVO.getIdList().parallelStream()
                .filter(goodsId -> !goodsIdList.contains(goodsId)).collect(Collectors.toList());
           
  • Map:Map类型不支持stream,新的方法
Map<Integer, String> map = new HashMap<>();
//putIfAbsent 不为null设值,否则返回
for (int i = 0; i < 10; i++) {
    map.putIfAbsent(i, "val" + i);
}
map.forEach((id, val) -> System.out.println(val));

map.computeIfPresent(3, (num, val) -> val + num);
map.get(3);             // val33

map.computeIfPresent(9, (num, val) -> null);
map.containsKey(9);     // false

map.computeIfAbsent(23, num -> "val" + num);
map.containsKey(23);    // true

map.computeIfAbsent(3, num -> "bam");
map.get(3);             // val33

map.remove(3, "val3");
map.get(3);             // val33

map.remove(3, "val33");
map.get(3);             // null

map.getOrDefault(42, "not found");  // not found

//merge 没有插入,否则合并
map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
map.get(9);             // val9

map.merge(9, "concat", (value, newValue) -> value.concat(newValue));
map.get(9);             // val9concat