Java 更改方法引用的类型

Java 更改方法引用的类型,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我的代码: class BlogPost { String title; String author; BlogPostType type; int likes; public BlogPost(String title, String author, BlogPostType type, int likes) { this.title = title; this.author = author; this

我的代码:

class BlogPost {
    String title;
    String author;
    BlogPostType type;
    int likes;

    public BlogPost(String title, String author, BlogPostType type, int likes) {
        this.title = title;
        this.author = author;
        this.type = type;
        this.likes = likes;
    }
//getter setter
}
以及:

以及:

publicstaticvoidmain(字符串[]args){
List posts=Arrays.asList(新的BlogPost(“启动Java”,“Ram”,BlogPostType.NEWS,11),
新的BlogPost(“启动Java 8”,“Rajou”,BlogPostType.REVIEW,101),
新的BlogPost(“函数式编程”,“Das”,BlogPostType.REVIEW,111),
新的BlogPost(“Lambda”,“Ramos”,blogpostype.GUIDE,541));
Map Blist=posts.stream().collect(groupingBy(BlogPost::getType));
System.out.println(Blist);
}}
我有三门课,一门是
BlogPost
blogpostype
Main

我正在使用
groupingBy()
制作
map Blist
的地图,效果非常好。我在那里使用了一个方法引用BlogPost::getType,我还可以使用lambda表达式
(x)->x.getType()

但是,当我尝试更改映射类型时,即
Map Blist1
,则无法使用方法引用。是否有任何可能的方法使用方法引用并使类型也发生更改

我在想为什么我们不能这样使用:
BlogPost::getType.toString()
(String)BlogPost::getType
,而我们可以在lambda
(x)->x.getType().toString()
中这样做。
使用方法引用和处理类型转换的任何可能方法?

方法引用就是对某个特定方法的“引用”

没有隐式转换或任何东西。只是一个具有特定签名的方法,并且语法快捷方式可以在不写lambda表达式的情况下表达它

如果要使用方法引用,则该对象必须作为方法存在。换句话说,您需要一种新方法,如

String getTypeAsString()
到您的
BlogPost
类。只有这样,您才能通过方法引用直接调用该方法

但在您的情况下,只需使用lambda表达式,而不是显式调用
toString()
。这里有一个与另一个方法“几乎”相同的特殊方法,只是为了让您能够写下一个方法引用,这听起来是错误的

或者,按照Eran回答中指出的有趣方法使用

最后,您的重点应该是编写对您和您的团队来说易于阅读和理解的代码。我个人的建议是在那里使用lambda,因为所有其他解决方案都只是添加了大量噪声,而没有真正的收益

方法引用代替lambda表达式使代码更加 可读,因此建议使用方法替换lambda表达式 参考,只要可能

请记住,方法引用将替换单个方法调用,在您的情况下,
BlogPost::getType
将正常工作,而
BlogPost::getType.toString()
将不工作,因为它不是单个方法调用


一个方法引用替换单个方法调用,因此它不能简单地替换由多个方法调用组成的lambda表达式,可以使用两个方法引用,如下所示,但我坚持使用lambda表达式,它要简单得多

Map<String, List<BlogPost>> Blist = 
    posts.stream()
         .collect(Collectors.groupingBy(((Function<BlogPost,BlogPostType>)BlogPost::getType).andThen(BlogPostType::toString)));
Map Blist=
posts.stream()
.collect(Collectors.groupingBy(((函数)BlogPost::getType)。然后(BlogPostType::toString));

函数getType=BlogPost::getType; 地图Blist= posts.stream() .collect(Collectors.groupingBy(getType.and(BlogPostType::toString));
您可以使用
Function.identity()
链接方法引用(根据需要)。例如,将以下函数放入
groupingBy

Function.<BlogPost>identity()
        .andThen(BlogPost::getType)
        .andThen(BlogPostType::toString)
Function.identity()
.然后(BlogPost::getType)
.然后(BlogPostType::toString)

但是最好使用lambda

我不相信您可以从方法引用中获得方法引用,比如
BlogPost::getType::toString
。您需要为此使用一个函数。请注意,我发现最好将枚举用作键,而不是
字符串
。对任何对象调用
toString
方法都不会转换类型!你想要达到的目标并不存在。一个lambda表达式到底有什么问题?我想坚持使用方法引用,如果可能的话,也可以通过强制转换来更改类型。但是。。。为什么?正如我在回答中所写的那样,方法引用并没有什么特别之处:它们只是lambda表达式的快捷方式。为什么你要强迫读者看一些比简单的lambda调用toString()更不清晰的东西@GhostCat是的,正如我所说的,我会坚持使用lambda表达式。方法链接似乎更容易理解,尽管无论何时何地,只要可能,人们都应该选择lambda。
Map<String, List<BlogPost>> Blist = 
    posts.stream()
         .collect(Collectors.groupingBy(((Function<BlogPost,BlogPostType>)BlogPost::getType).andThen(BlogPostType::toString)));
Function<BlogPost,BlogPostType> getType = BlogPost::getType;
Map<String, List<BlogPost>> Blist = 
    posts.stream()
         .collect(Collectors.groupingBy(getType.andThen(BlogPostType::toString)));
Function.<BlogPost>identity()
        .andThen(BlogPost::getType)
        .andThen(BlogPostType::toString)