简体   繁体   中英

Change Type of Method Reference

My code:

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
}

and:

public enum BlogPostType {
    NEWS,
    REVIEW,
    GUIDE
}

and:

public static void main(String[] args) {
        List<BlogPost> posts = Arrays.asList(new BlogPost("Start Java", "Ram", BlogPostType.NEWS, 11),
            new BlogPost("Start Java 8", "Rajou", BlogPostType.REVIEW, 101),
            new BlogPost("Functional programming", "Das", BlogPostType.REVIEW, 111),
            new BlogPost("Lambda", "Ramos", BlogPostType.GUIDE, 541));

        Map<BlogPostType, List<BlogPost>> Blist = posts.stream().collect(groupingBy(BlogPost::getType));
        System.out.println(Blist);
}}

I have three classes one is BlogPost , BlogPostType and Main .

I am making a map of Map<BlogPostType, List<BlogPost>> Blist by using groupingBy() and it works perfectly fine. i used a method reference there BlogPost::getType , i can use lambda expression also (x) -> x.getType() .

But when i try to change the type of Map , ie Map<String, List<BlogPost>> Blist1 then i cannot use Method reference . Is there any possible way to use method reference and get the type also changed??

I am thinking why cant we use like this: BlogPost::getType.toString() or (String)BlogPost::getType while we can do this in lambda (x) -> x.getType().toString() . Any possible ways to use Method reference and get along with conversion of type also?

A method reference is just that: a "reference" to some specific method.

There is no implicit conversion or anything. Just a method that has a certain signature, and syntactic shortcut to express that without writing down a lambda expression.

If you want to use a method reference, that thing must exist as method. In other words, you would need to a new method like

String getTypeAsString()

to your BlogPost class. Only then you can go and directly invoke that method via a method reference.

But in your case, simply use that lambda expression instead that calls toString() explicitly. It sounds wrong to have a special method there that does "almost" the same as another method, just to enable you to write down a method reference.

Alternatively, follow the interesting approach pointed out in Eran's answer to use andThen() .

In the end, your focus should be to write code that is easy to read and understand for you and your team. My personal recommendation would be to use the lambda right there, as all other solutions just add a lot of noise for no real gain.

Method reference in place of lambda expression makes your code more readable, hence it is advised to replace lambda expression with method reference, Whenever Possible .

Remember a method reference replace a single method invocation , in your case BlogPost::getType will work fine while BlogPost::getType.toString() will not work as it is not single method invocation.

A method reference replace a single method invocation, so it can't simply replace a lambda expression consisting of more than one method invocation .

You can do it with two method references as follows, but I'd stick with the lambda expression, which is much simpler.

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

or

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

you can use Function.identity() to chain method references (as many as you want). For example, put the following function in groupingBy :

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

but it's better to use lambda

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM