在Java8中,如何保证不重复投射?

In Java8, how to ensure repeated casting is not used?

我在Java中有以下过滤函数:

public static <T> void filter(List<T> items, Predicate condition)
{   
    System.out.print("\t");
    for(T element : items)
    {   
        if (condition.test(element))
        {   
            System.out.print(element + " "); 
        }   
    }   
    System.out.println("");
}   

我尝试将其称为:

List <String> cities = Arrays.asList("Chennai", "New Delhi", 
        "Mumbai", "Pune", "Madurai", "Bhopal", "Bilaspur");
filter(cities, (String str)->str.startsWith("B") ||
        str.startsWith("C") ||str.startsWith("M"));

但是,我收到以下错误,指向 String str as:

incompatible parameter types in lambda expression

如果我删除 strString 前缀,那么我必须更改每个 str 在条件链中出现 ((String) str).startsWith("B") || ... 这确实很冗长。

发生这种情况是因为您将参数化 class Predicate 用作原始 class,而不是利用泛型。您应该将 Predicate 更改为 Predicate<T>,然后您的代码将起作用,并且您可以删除 String 前缀。

Predicate 本质上类似于 Predicate<Object>,因此您的 filter() 方法期望第二个参数是对 Object 进行操作的谓词。但是,您正试图传递 Predicate<String>。由于 Predicate<String> 不是 Predicate<Object>,您会收到编译错误。

将参数更改为 Predicate<T> 后,您的 lambda 表达式不再需要显式表示 String str,因为只需输入 str,它就会自动求值为 Predicate<String> 使用类型推断。

你只需要添加一个类型参数到Predicate

    public static <T> void filter(List<T> items, Predicate<T> condition)
                                                          ^^^

这允许类型检查器推断调用中的 lambda 表达式必须采用 String 参数。


但是如果您担心演员表的冗长,那么您将忽略 "elephant in the room"。

您不需要编写 12 行的自定义 filter 方法来执行此操作。 Stream API 提供了大约 3 行所需的所有内容。

List <String> cities = Arrays.asList("Chennai", "New Delhi", 
    "Mumbai", "Pune", "Madurai", "Bhopal", "Bilaspur");
System.out.println(cities.stream()
                         .filter(str->str.startsWith("B") ||
                                      str.startsWith("C") ||
                                      str.startsWith("M"))
                         .collect(Collectors.joining(" ")));

filter有标准的Stream::filter方法。迭代由 stream() 完成,space 分隔字符串的组装由 joining 收集器完成。