Java8学习手册

常用

对Map进行排序

  1. 将 Map 转换为 Stream
  2. 对其进行排序
  3. Collect and return a new LinkedHashMap (保持顺序)
Map result = map.entrySet().stream()
	.sorted(Map.Entry.comparingByKey())
	.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
	(oldValue, newValue) -> oldValue, LinkedHashMap::new));

函数

函数其实就是匿名内部类

public interface Checker{
    boolean doCheck(String name);
}

函数的声明lamda化

没有java8之前
new Checker() {
    @Override
    public boolean doCheck(String name) {
           return StringUtils.isBlank(name);
    }
};

有了java8后,可以用lamda表达式声明,跟js一样的,不作详解
(String name)->{
    return StringUtils.isBlank(name);
}

新增函数类型返回值

没有java8之前,返回Checker对象
Checker checker = new Checker() {
    @Override
    public boolean doCheck(String name) {
           return StringUtils.isBlank(name);
    }
};

有了java8后,可以用lamda表达式声明,返回函数对象
Function function = (String name)->{
    return StringUtils.isBlank(name);
}

注意!Function function = (String name)-> {xx},这里的Function用于指代"函数式接口",仅是指代,因为"函数式接口"根据入参、出参的不同,分为了很多具体的对象。

新增方法调用方式::

:: 可以用于调用静态方法,构造方法,成员方法,并返回一个函数式接口,调用不同的方法会返回不同的函数式接口。

 public static class Apple{
        private String name;

        // 构造方法
        public Apple() {

        }

        // 有参构造方法
        public Apple(String name) {
            this.name = name;
        }

        // 无入参、有出参的构造方法
        public String getName() {
            return name;
        }

        // 有入参、无出参的构造方法
        public void setName(String name) {
            this.name = name;
        }

        // 静态方法
        public static String say() {
            return "welcome to wonder land";
        }
    }

调用构造方法

psvm() {
        // 调用无参构造器
        Supplier<Apple> aNew = Apple::new;
        Apple apple = aNew.get();
        
        // 调用有参构造器
        Function<String,Apple> function = Apple::new;
        Apple onion = function.apply("onion");
        System.out.println(onion.getName());
}

注意!可见同样是::调用构造方法,调用无参构造器、有参构造器,会返回不同的函数类型。

调用成员方法

psvm() {
        Apple apple = new Apple();

        Consumer<String> setName = apple::setName;
        setName.accept("onion");

        Supplier<String> getName =  apple::getName;
        String name = getName.get();
        System.out.println(name);
}

调用静态方法

psvm(){
    Supplier<String> say = Apple::say;
    String s = say.get(); // 会返回welcome to wonder land
}

缤纷多彩的函数式接口

Predicate 接受一个泛型入参,返回boolean

// 这个是没法跑的,因为该lamda表达式真正返回的是Predicate函数式接口
Function function = (String name)->{
    return StringUtils.isBlank(name);
}

// 这样才是能跑的
Predicate<String> predicate = (String name)->{
    return StringUtils.isBlank(name);
}

// test,直接对入参执行判断
psvm() {
    Predicate<String> predicate = (String name)->{
        return StringUtils.isBlank(name);
    };
    predicate.test("onion");// 非空,返回false
}

// and,组合判断
psvm() {
    Predicate<String> a = (String name)->{
        return StringUtils.isNotBlank(name);
    };
    Predicate<String> b = (String name)->{
        return "onion".equals(name);
    };
    boolean b = a.and(b).test("onion"); // 非空且等于onion,返回true
}

// or,组合判断
psvm() {
    Predicate<String> a = (String name)->{
        return StringUtils.isBlank(name);
    };
    Predicate<String> b = (String name)->{
        return "onion".equals(name);
    };
    boolean b = a.or(b).test("onion"); // 空 或 等于onion,返回true
}

// negate,取反
psvm() {
    Predicate<String> a = (String name)->{
        return StringUtils.isBlank(name);
    };
    boolean b = a.negate().test("onion"); // 非空,则返回true
}

// equal,没啥用,null跟null比,否则用equals比
psvm() {
     Predicate<Object> equal = Predicate.isEqual("123");
     System.out.println(equal.test("123"));
}

Supplier<

Java8 Stream

stream:将集合变成流,流过一个管道(pipeline),可以在管道中增加中间节点对流进行处理(intermediate operations),也可以在管道终点增加收集聚合操作对零散的流进行收集或聚合(terminal operation)。

intermediate operation

  • 去重(distinct)
  • 排序(sorted)
  • 过滤(filter)
  • 将每个元素通过函数映射成另外的元素形成新流(map),特别是将元素通过函数转为int/long流(mapToInt,mapToLong,mapToDouble)
  • 合并起来替换原来的流(flatMap,flatMapToInt,flatMapToLong,flatMapToDouble)
  • 元素即将进入下一个节点前执行前置动作(peek)
  • 取头几个被处理的元素(limit)
  • 跳过前面n个元素仅保留后半部分(skip)

terminal operation

  • 简单收集(collect)
  • 取最小值(min)
  • 取最大值(max)
  • 统计个数(count)
  • 是否有元素满足(anyMatch)
  • 是否所有元素满足(allMatch)
  • 是否没有元素满足(noneMatch)
  • 取集合第一个元素Optional(findFirst)

中间处理 intermediate operations

在管道的中间增加节点对流进行处理,处理后返回的仍然是流。

【Java8 Stream】终点处理 terminal operation

在管道的终点对流进行处理,要么把流简单收集,要么把流收集后聚合,总之处理后返回的不再是流了。

终点处理一般靠collect和Collectors配合完成

<R, A> R collect(Collector<? super T, A, R> collector)

1. collect用于将流收集后,进行聚合或统计操作。

2. java8提供了Collectors接口,配合collect操作做一些常用的聚合统计操作。

简单收集简单收集成List、set
收集成treeSet等复杂的集合
收集成一个用逗号分隔的字符串
收集成map,也就是常说的list转map
算术summingInt,算总数,还有其他sum方法大同小异
averagingInt算平均数,还有其他average方法大同小异
聚合分组

按对象的某个属性分组

  • 将对象列表分组,分组后每组组员为原对象
  • 将对象列表分组,分组后每组组员为对象的属性,或其他和原对象有映射关系的对象
按某个断言分组
组合分组,先按某个条件分组,对分组结果再按某个条件分组

【简单收集】简单收集成List、set

// 简单收集成List、set
psvm() {
     ArrayList<String> arr = Lists.newArrayList("4", "1", "3");
     List<String> collect = arr.stream().collect(Collectors.toList());

     List<String> collect = arr.stream().collect(Collectors.toSet());
}

// 收集成treeSet等复杂的集合
psvm() {
      ArrayList<String> arr = Lists.newArrayList("4", "1", "3","3");
      TreeSet<String> collect = arr.stream().collect(Collectors.toCollection(TreeSet::new));
      collect.stream().forEach(System.out::println); // 打印1、3、4
}

// 收集成一个用逗号分隔的字符串
psvm() {
        ArrayList<String> arr = Lists.newArrayList("4", "1", "3","3");
        String collect = arr.stream().collect(Collectors.joining(","));
        System.out.println(collect); // 打印4,1,3,3
}

将对象列表分组,分组后每组组员为对象的属性,或其他和原对象有映射关系的对象

本来apples按颜色分组,每组组员应该是apple对象才对,现在将组员映射成apple的批次号。

List<Apple> list = ...;
Map<String, Set<Long>> schSkuMap = list.stream().collect(
    Collectors.groupingBy(Apple::getColor,
        Collectors.mapping(Apple::getBatchNo, Collectors.toSet())
    )
);

【简单收集】收集成map

不存在重复key时,属性->属性

// 收集成map
psvm() {
    ArrayList<Person> people = Lists.newArrayList(
                new Person("onion", 17),
                new Person("liyc", 17));
    Map<String, Integer> collect = people.stream().collect(Collectors.toMap(p -> p.getName(), p -> p.getAge()));
    System.out.println(JSONObject.toJSONString(collect)); // 打印 {"liyc":17,"onion":17}
}

不存在重复key时,属性->对象 或 对象->属性

psvm() {
    Map<String, Person> collect = people.stream().collect(Collectors.toMap(p -> p.getName(), Function.identity()));
    System.out.println(JSONObject.toJSONString(collect));
    // 打印{"liyc":{"age":17,"name":"liyc"},"onion":{"age":15,"name":"onion"}}
}


psvm() {
    Map<String, Person> collect = people.stream().collect(Collectors.toMap(Function.identity(), p->p.getName()));
    System.out.println(JSONObject.toJSONString(collect));
    // 打印{{"age":15,"name":"onion"}:"onion",{"age":17,"name":"liyc"}:"liyc"}
}

存在重复key时,去重

@AllArgsConstructor
@NoArgsConstructor
@Data
public static class House{
        private String name;
        private String address;
}


psvm(){
        ArrayList<House> people = Lists.newArrayList(new House("onion", "a district"),
                new House("onion","b district"),
                new House("liyc","c district"),
                new House("liyc", "e district"));

        Map<String, String> collect1 = people.stream().collect(Collectors.toMap(House::getName, House::getAddress, (s, a) -> a));
        System.out.println(JSONObject.toJSONString(collect1));
       // 打印 {"liyc":"e district","onion":"b district"}
}

存在重复key时,合并value返回

@AllArgsConstructor
@NoArgsConstructor
@Data
public static class House{
        private String name;
        private String address;
}


psvm() {
      Map<String, String> collect2 = people.stream().collect(Collectors.toMap(House::getName, House::getAddress, (s, a) -> s + "," + a));
      System.out.println(JSONObject.toJSONString(collect2));
      // 打印{"liyc":"c district,e district","onion":"a district,b district"}
}

算术类Collectors

// 算总数,还有其他sum方法大同小异
psvm(){
    ArrayList<String> arr = Lists.newArrayList("4", "1", "3","3");
    Integer collect = arr.stream().collect(Collectors.summingInt(Integer::valueOf));
    System.out.println(collect);
}

聚合分组类Collectors

// 按某个属性分组
psvm() {
    ArrayList<Person> people = Lists.newArrayList(new Person("onion", 15),
                new Person("onion", 17),
                new Person("liyc", 15),
                new Person("liyc", 18));

    Map<String, List<Person>> collect = people.stream().collect(Collectors.groupingBy(Person::getName));
    System.out.println(JSONObject.toJSONString(collect)); 
    // 打印 {"liyc":[{"age":15,"name":"liyc"},{"age":18,"name":"liyc"}],"onion":[{"age":15,"name":"onion"},{"age":17,"name":"onion"}]}
}

// 按某个断言分组
psvm() {
     ArrayList<Person> people = Lists.newArrayList(new Person("onion", 15),
                new Person("onion", 17),
                new Person("liyc", 15),
                new Person("liyc", 18));

     Map<Boolean, List<Person>> collect = people.stream().collect(Collectors.partitioningBy((item) -> item.getAge() > 15));
     System.out.println(JSONObject.toJSONString(collect));
     // 打印{false:[{"age":15,"name":"onion"},{"age":15,"name":"liyc"}],true:[{"age":17,"name":"onion"},{"age":18,"name":"liyc"}]}
}

// 组合分组,先按某个条件分组,对其分组结果再按另外条件分组
psvm() {
      // 先按name分组,把分组结果,再按是否大于15岁分组
      ArrayList<Person> people = Lists.newArrayList(new Person("onion", 15),
                new Person("onion", 17),
                new Person("liyc", 15),
                new Person("liyc", 17));
      Map<String, Map<Boolean, List<Person>>> collect = people.stream().collect(Collectors.groupingBy(Person::getName, Collectors.partitioningBy(item -> item.getAge() > 15)));
      System.out.println(JSONObject.toJSONString(collect));
      //打印 {"liyc":{false:[{"age":15,"name":"liyc"}],true:[{"age":17,"name":"liyc"}]},"onion":{false:[{"age":15,"name":"onion"}],true:[{"age":17,"name":"onion"}]}}

     // 先按名字分组,再取每个分组年龄最大的人
     Map<String, Optional<Person>> collect1 = people.stream().collect(Collectors.groupingBy(Person::getName, Collectors.maxBy(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
     })));
     System.out.println(JSONObject.toJSONString(collect1));
     // 打印{"liyc":{"age":17,"name":"liyc"},"onion":{"age":17,"name":"onion"}}
}

Optional从容面对空指针

// 返回空的 Optional 实例。
static <T> Optional<T> empty()

// 判断其他对象是否等于 Optional, null跟null比,有值则optional内部的值与值比
boolean equals(Object obj)

// 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的
Optional<T> filter(Predicate<? super <T> predicate)

// 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

// 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
T get()

// 返回存在值的哈希码,如果值不存在返回 0
int hashCode()

// 如果值存在则使用该值调用 consumer , 否则不做任何事情。
void ifPresent(Consumer<? super T> consumer)

// 如果值存在则方法会返回true,否则返回 false。
boolean isPresent()

// 如果存在该值,提供的映射方法,如果返回非null,返回一个Optional描述结果。
<U>Optional<U> map(Function<? super T,? extends U> mapper)

// 返回一个指定非null值的Optional。
static <T> Optional<T> of(T value)

// 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
static <T> Optional<T> ofNullable(T value)

// 如果存在该值,返回值,否则返回 other
T orElse(T other)

// 如果存在该值,返回值,否则触发 other,并返回 other 调用的结果。
T orElseGet(Supplier<? extends T> other)

// 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值