在Java8中,如何确保不使用重复转换?

我在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为:

incompatible parameter types in lambda expression

如果我将字符串前缀删除为str,则必须将条件链中每个出现的str更改为((String)str).startsWith(“ B”)|| ...固然很冗长。

评论
hculpa
hculpa

This is happening because you're using the parameterized class Predicate as a raw class, instead of leveraging generics. You should change Predicate to Predicate<T>, and then your code will work, and you can remove the String prefix.

Predicate is essentially like Predicate<Object>, so your filter() method expects the second argument to be a predicate that operates on Objects. However, you're attempting to pass a Predicate<String> instead. Since a Predicate<String> isn't a Predicate<Object>, you're getting that compile error.

Once you change the parameter to Predicate<T>, your lambda expression no longer needs to explicitly say String str, since by just putting str it will automatically evaluate to a Predicate<String> using type inference.

点赞
评论
Seven
Seven

You just need to add a type parameter to Predicate.

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

This allows the type checker to infer that the lambda expression in the call must take a String parameter.

But you don't need to write a custom filter method to do this.

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(" ")));

The filter there is the standard Stream::filter method. The iteration is done by stream() and the assembly of a space-separated string is done by the joining collector.

点赞
评论