Java 8 个 Lambda 表达式

Java 8 Lambda Expressions

我一直坚持使用一个 lambda 表达式和比较器 class 使用 Comparator.comparing(...).thenComparing(...) 方法来总结两种对流进行排序的方法。

我的两种方法都有效,但是当我把它们放在一起时,什么都不管用。

这里是 link 如果你想尝试验证这个练习:

http://codecheck.it/codecheck/files?repo=heigvdcs1&problem=poo3e

这是你必须做的:

对于流中的每个单词,确定“元音”,即元音的数量 - 辅音的数量。生成元音最高的 n 个词与元音值配对。首先按元音排序,然后按字符串排序。完成这个程序。 这一次,您有一个隐藏的静态方法 long Words.vowels(String w) 供您使用,它会产生 w 中的元音数量,包括重复的。

目前我已经做到了:

import java.util.*;
import java.util.stream.*;

public class Streams
{
   List<Pair<String, Long>> wordsWithManyVowels(Stream<String> words, int n)
   {
      return words
         .map( w -> Pair.of( w , ( Words.vowels(w) - ( w.length() - Words.vowels(w)))))
         .sorted(Comparator.comparingLong(f1 -> -f1.second())
         //This part is working without the first comparing
         //.thenComparing(f2 -> f2.first().length()))
         .limit(n)
         .collect(Collectors.toList());
   }
}

一对class:

import java.util.Objects;

public class Pair<T, S> 
{
   private T first;
   private S second;

   public Pair(T firstElement, S secondElement)
   {
      first = firstElement;
      second = secondElement;
   }

   /*
      Use Pair.of(x, y) instead of new Pair<...,...>(x, y)
      so you get the type inferred
   */

   public static <T, S> Pair<T, S> of(T firstElement, S secondElement)
   {
      return new Pair<T, S>(firstElement, secondElement);
   }

   public T first() { return first; }
   public S second() { return second; }

   public String toString() { return "(" + first + "," + second + ")"; }

   public boolean equals(Object otherObject)
   {
      if (this == otherObject) 
         return true;
      if (otherObject == null || !(otherObject instanceof Pair)) 
         return false;
      @SuppressWarnings("unchecked") Pair<T, S> other = (Pair<T, S>) otherObject;
      return Objects.equals(first, other.first) &&
         Objects.equals(second, other.second);
   }
}

解决方案 1

提取比较方法 static 就像这样

public class Streams {
    List<Pair<String, Long>> wordsWithManyVowels(Stream<String> words, int n) {
        return words
            .map(w -> Pair.of(w, (Words.vowels(w) - (w.length() - Words.vowels(w)))))
            .sorted(Comparator.comparingLong(Streams::vowelness).thenComparingInt(Streams::length))
            .limit(n)
            .collect(Collectors.toList());
    }

    static int length(Pair<String, Long> p) {
        return p.first().length();
    }

    static long vowelness(Pair<String, Long> p) {
        return -p.second();
    }
}

解决方案 2

在没有 static 方法的情况下使用此 Comparator 实现

Comparator
    .comparingLong((Pair<String, Long> p) -> -p.second())
    .thenComparingInt((Pair<String, Long> p) -> p.first().length())

注意:看一下thenComparingInt是如何用在两种方案的复合比较器的末尾的。

解决方案 3

源代码的问题是静态的Comparator方法需要有关链中处理元素类型的信息。默认使用 Object 类型。因此,可以这样指定它(比解决方案 2 更简单):

Comparator.<Pair<String, Long>>comparingLong(p -> -p.second()).thenComparing(p -> p.first().length())