Java 8 函数式编程(4)

本篇对应《Java 8 函数式编程》第 5 章。


要点回顾

  1. 方法 引用 是一 种 引用 方法 的 轻量级 语法, 形如: ClassName:: methodName。
  2. 收集 器 可用 来 计算 流的 最 终值, 是 reduce 方法 的 模拟。
  3. Java 8 提供 了 收集 多种 容器 类型 的 方式, 同时 允许 用户 自定义 收集器。

练习

Question 1:

https://leetcode.com/playground/KrzQMGgR

public static void subquestionA() {
        List<String> collected = Stream.of("a", "b", "hello")
                                       .map(String::toUpperCase)
                                       .collect(Collectors.toList());
        System.out.println(collected);
    }
    
    public static void subquestionB() {
        int count = Stream.of(1, 2, 3)
                          .reduce(0, Integer::sum);
        System.out.println(count);
    }
    
    public static void subquestionC() {
        List<Integer> together = Stream.of(Arrays.asList(1,2), Arrays.asList(3,4))
                                       .flatMap(List::stream)
                                       .collect(Collectors.toList());
        System.out.println(together);
    }

Question 2:

LongestName.java

public class LongestName {

    private static Comparator<Artist> byNameLength = comparing(artist -> artist.getName().length());

    public static Artist byReduce(List<Artist> artists) {
        return artists.stream()
                      .reduce((acc, artist) -> {
                          return (byNameLength.compare(acc, artist) >= 0) ? acc : artist;
                      })
                      .orElseThrow(RuntimeException::new);
    }

    public static Artist byCollecting(List<Artist> artists) {
        return artists.stream()
                      .collect(Collectors.maxBy(byNameLength))
                      .orElseThrow(RuntimeException::new);
    }

}

WordCount.java

public class WordCount {

    public static Map<String, Long> countWords(Stream<String> names) {
        return names.collect(groupingBy(name -> name, counting()));
    }

}

GroupingBy.java

public class GroupingBy<T, K> implements Collector<T, Map<K, List<T>>, Map<K, List<T>>> {

    private final static Set<Characteristics> characteristics = new HashSet<>();
    static {
        characteristics.add(Characteristics.IDENTITY_FINISH);
    }

    private final Function<? super T, ? extends K> classifier;

    public GroupingBy(Function<? super T, ? extends K> classifier) {
        this.classifier = classifier;
    }

    @Override
    public Supplier<Map<K, List<T>>> supplier() {
        return HashMap::new;
    }

    @Override
    public BiConsumer<Map<K, List<T>>, T> accumulator() {
        return (map, element) -> {
            K key = classifier.apply(element);
            List<T> elements = map.computeIfAbsent(key, k -> new ArrayList<>());
            elements.add(element);
        };
    }

    @Override
    public BinaryOperator<Map<K, List<T>>> combiner() {
        return (left, right) -> {
            right.forEach((key, value) -> {
                left.merge(key, value, (leftValue, rightValue) -> {
                    leftValue.addAll(rightValue);
                    return leftValue;
                });
            });
            return left;
        };
    }

    @Override
    public Function<Map<K, List<T>>, Map<K, List<T>>> finisher() {
        return map -> map;
    }

    @Override
    public Set<Characteristics> characteristics() {
        return characteristics;
    }

}

Question 3:

Fibonacci.java

public class Fibonacci {

    private final Map<Integer,Long> cache;

    public Fibonacci() {
        cache = new HashMap<>();
        cache.put(0, 0L);
        cache.put(1, 1L);
    }

    public long fibonacci(int x) {
        return cache.computeIfAbsent(x, n -> fibonacci(n-1) + fibonacci(n-2));
    }

}

参考:

74 total views, 1 views today

Java 8 函数式编程(3)

本篇对应《Java 8 函数式编程》的第四章。


要点回顾

  1. 使用为基本类型定制的Lambda表达式和Stream,如IntStream可以显著提升系统性能。
  2. 默认方法是指接口中定义的包含方法体的方法,方法名有default关键字做前缀。
  3. 在一个值可能为空的建模情况下,使用Optional对象能替代使用null值。

练习

Question 1:

/** 该接口表示艺术家的演出——专辑或演唱会 */
public interface Performance {

    public String getName();

    public Stream<Artist> getMusicians();

    public default Stream<Artist> getAllMusicians() {
        return getMusicians()
              .flatMap(artist -> concat(Stream.of(artist), artist.getMembers()));
    }

}

Question2:

不能。

public interface Parent {
    default public boolean equals(Object object) {
        return true;
    }

    default public int hashCode() {
        return 1;
    }
}
% javac Parent.java
Parent.java:2: error: default method equals in interface Parent overrides a member of java.lang.Object
    default public boolean equals(Object object) {
                           ^
Parent.java:6: error: default method hashCode in interface Parent overrides a member of java.lang.Object
    default public int hashCode() {
                       ^
2 errors

Question 3:

public class Artists {

    private List<Artist> artists;

    public Artists(List<Artist> artists) {
        this.artists = artists;
    }

    public Optional<Artist> getArtist(int index) {
        if (index < 0 || index >= artists.size()) {
            return Optional.empty();
        }
        return Optional.of(artists.get(index));
    }

    public String getArtistName(int index) {
        Optional<Artist> artist = getArtist(index);
        return artist.map(Artist::getName)
                     .orElse("unknown");
    }

}

参考:

166 total views, 1 views today