有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

有没有解释为什么Java8Lambda表达式使用函数变量而不内联工作

有人能解释为什么我把lambda表达式放进直升机里吗。在下面的代码中,compring()不起作用。当我将相同的表达式提取到函数变量中时,它工作得很好

有两个示例(在Main.java类中),其中一个没有编译(可选),另一个正在编译,但在执行时抛出错误。我在注释中加入了不起作用的代码,以表明当表达式被提取到变量中时,它可以正常工作

package com.slide;

import java.time.LocalDate;
import java.time.Month;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

import static java.util.Comparator.*;
import static java.util.Comparator.reverseOrder;

public class Main {

    static class Book {
        private int price;
        private LocalDate date;
        private Author author;

        public Book(int price, LocalDate date, Author author) {
            this.price = price;
            this.date = date;
            this.author = author;
        }

        public int getPrice() { return price; }
        public void setPrice(int price) { this.price = price; }
        public LocalDate getDate() { return date; }
        public void setDate(LocalDate date) { this.date = date; }
        public Author getAuthor() { return author; }
        public void setAuthor(Author author) { this.author = author; }

        @Override
        public String toString() {
            String authorName = author != null && author.getName() != null ? author.getName() : "null";
            return "{ price : "
                    .concat(String.valueOf(price))
                    .concat(", year : ")
                    .concat(date != null ? date.toString() : "null")
                    .concat(", author : ")
                    .concat(authorName)
                    .concat("}");
        }
    }

    static class Author {
        private String name;

        public Author(String name) {
            this.name = name;
        }

        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
    }

    static Author john = new Author("John");
    static Author marguerite = new Author("Marguerite");
    static Author charlton = new Author("Charlton");
    static Author gwen = new Author("Gwen");
    static Author marion = new Author("Marion");
    static Author mark = new Author("Mark");
    static Author jerry = new Author("Jerry");
    static Author bob = new Author("Bob");
    static Author dennis = new Author("Dennis");
    static Author mike = new Author(null);


    static Book b1 = new Book(15, LocalDate.of(1983, Month.JANUARY, 1), john);
    static Book b2 = new Book(8, LocalDate.of(1998, Month.AUGUST, 1), marguerite);
    static Book b3 = new Book(14, LocalDate.of(1992, Month.SEPTEMBER, 1), john);
    static Book b4 = new Book(10, LocalDate.of(2016, Month.MAY, 1), charlton);
    static Book b5 = new Book(10, LocalDate.of(1997, Month.FEBRUARY, 1), gwen);
    static Book b6 = new Book(8, LocalDate.of(1986, Month.AUGUST, 1), charlton);
    static Book b7 = new Book(54, LocalDate.of(1998, Month.MARCH, 1), john);
    static Book b8 = new Book(10, LocalDate.of(1997, Month.FEBRUARY, 1), marion);
    static Book b9 = new Book(32, LocalDate.of(2013, Month.JULY, 1), mark);
    static Book b10 = new Book(5, LocalDate.of(1997, Month.AUGUST, 1), jerry);
    static Book b11 = new Book(10, LocalDate.of(2008, Month.MAY, 1), bob);
    static Book b12 = new Book(9, LocalDate.of(1978, Month.FEBRUARY, 1), dennis);
    static Book b13 = new Book(10, LocalDate.of(1995, Month.FEBRUARY, 1), mike);
    static Book b14 = new Book(10, LocalDate.of(1995, Month.FEBRUARY, 1),null);

    public static List<Book> givenBooksWithNulls(){
        return Arrays.asList(b1, b2, b3, b4, null, b5, b6, b7, b8, null, b13, b9, b10, b14, b11, b12);
    }

    public static void main(String[] args) {
        List<Book> books = givenBooksWithNulls();
        Function<Book, Integer> fPrice = b -> b == null ? null : b.getPrice();
        Function<Book, String> fAuthor = b -> b == null ? null : b.getAuthor() == null ? null : b.getAuthor().getName();
        // Woks good with the Functions as Variables
        books.stream()
                .filter(b -> b == null || b.getDate().getYear() > 1990)
                .sorted(comparing(fPrice, nullsLast(naturalOrder()))
                        .thenComparing(fAuthor, nullsLast(reverseOrder()))
                )
                .forEach(System.out::println);

        // It doesn't work when I put the content of the Functions inline
        // Java says getPrice() cannot be find in java.lang.Object
        // it seems like comparing doesn't like the Lambda expression
//        books.stream()
//                .filter(b -> b == null || b.getDate().getYear() > 1990)
//                .sorted(comparing(b -> b == null ? null : b.getPrice(), nullsLast(naturalOrder()))
//                        .thenComparing(b -> b == null ? null : b.getAuthor() == null ? null : b.getAuthor().getName(), nullsLast(reverseOrder()))
//                )
//                .forEach(System.out::println);


        System.out.println("====================================");

        // Other example using Optional

        Predicate<Book> fFilter = b -> Optional.ofNullable(b)
                .map(bb -> bb.getDate().getYear() > 1990)
                .orElse(false);

        Function<Book, Integer> fPrice2 = b -> Optional.ofNullable(b)
                .map(Book::getPrice)
                .orElse(null);

        Function<Book, String> fAuthor2 = b -> Optional.ofNullable(b)
                .map(Book::getAuthor)
                .map(Author::getName)
                .orElse(null);

        // This also works when I use the Predicate and Functions as variables
        givenBooksWithNulls().stream()
                .filter(fFilter)
                .sorted(comparing(fPrice2, nullsLast(naturalOrder()))
                        .thenComparing(fAuthor2, nullsLast(reverseOrder()))
                )
                .forEach(System.out::println);

        // Same thing Here, not working when we replace the variables by their content of Lambda expression
//        givenBooksWithNulls().stream()
//                .filter(b -> Optional.ofNullable(b)
//                        .map(bb -> bb.getDate().getYear() > 1990)
//                        .orElse(false))
//                .sorted(comparing(b -> Optional.ofNullable(b)
//                        .map(Book::getPrice)
//                        .orElse(null), nullsLast(naturalOrder()))
//                        .thenComparing(b -> Optional.ofNullable(b)
//                                .map(Book::getAuthor)
//                                .map(Author::getName)
//                                .orElse(null), nullsLast(reverseOrder()))
//                )
//                .forEach(System.out::println);
    }
}

更新:

我在这个更新中为那些喜欢分离代码的人分离代码

作者。爪哇

package com.slide;

public class Author {
    private String name;

    public Author(String name) {
        this.name = name;
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

书。爪哇

package com.slide;

import java.time.LocalDate;

public class Book {
    private int price;
    private LocalDate date;
    private Author author;

    public Book(int price, LocalDate date, Author author) {
        this.price = price;
        this.date = date;
        this.author = author;
    }

    public int getPrice() { return price; }
    public void setPrice(int price) { this.price = price; }
    public LocalDate getDate() { return date; }
    public void setDate(LocalDate date) { this.date = date; }
    public Author getAuthor() { return author; }
    public void setAuthor(Author author) { this.author = author; }

    @Override
    public String toString() {
        String authorName = author != null && author.getName() != null ? author.getName() : "null";
        return "{ price : "
                .concat(String.valueOf(price))
                .concat(", year : ")
                .concat(date != null ? date.toString() : "null")
                .concat(", author : ")
                .concat(authorName)
                .concat("}");
    }
}

数据示例。爪哇

package com.slide;

import java.time.LocalDate;
import java.time.Month;
import java.util.Arrays;
import java.util.List;

public class DataExample {
    static Author john = new Author("John");
    static Author marguerite = new Author("Marguerite");
    static Author charlton = new Author("Charlton");
    static Author gwen = new Author("Gwen");
    static Author marion = new Author("Marion");
    static Author mark = new Author("Mark");
    static Author jerry = new Author("Jerry");
    static Author bob = new Author("Bob");
    static Author dennis = new Author("Dennis");
    static Author mike = new Author(null);


    static Book b1 = new Book(15, LocalDate.of(1983, Month.JANUARY, 1), john);
    static Book b2 = new Book(8, LocalDate.of(1998, Month.AUGUST, 1), marguerite);
    static Book b3 = new Book(14, LocalDate.of(1992, Month.SEPTEMBER, 1), john);
    static Book b4 = new Book(10, LocalDate.of(2016, Month.MAY, 1), charlton);
    static Book b5 = new Book(10, LocalDate.of(1997, Month.FEBRUARY, 1), gwen);
    static Book b6 = new Book(8, LocalDate.of(1986, Month.AUGUST, 1), charlton);
    static Book b7 = new Book(54, LocalDate.of(1998, Month.MARCH, 1), john);
    static Book b8 = new Book(10, LocalDate.of(1997, Month.FEBRUARY, 1), marion);
    static Book b9 = new Book(32, LocalDate.of(2013, Month.JULY, 1), mark);
    static Book b10 = new Book(5, LocalDate.of(1997, Month.AUGUST, 1), jerry);
    static Book b11 = new Book(10, LocalDate.of(2008, Month.MAY, 1), bob);
    static Book b12 = new Book(9, LocalDate.of(1978, Month.FEBRUARY, 1), dennis);
    static Book b13 = new Book(10, LocalDate.of(1995, Month.FEBRUARY, 1), mike);
    static Book b14 = new Book(10, LocalDate.of(1995, Month.FEBRUARY, 1),null);

    public static List<Book> givenBooksWithNulls(){
        return Arrays.asList(b1, b2, b3, b4, null, b5, b6, b7, b8, null, b13, b9, b10, b14, b11, b12);
    }
}

梅因。爪哇

package com.slide;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

import static java.util.Comparator.*;
import static java.util.Comparator.reverseOrder;

public class Main {

    public static void main(String[] args) {
        List<Book> books = DataExample.givenBooksWithNulls();
        exampleOne(books);
        System.out.println("====================================");
        exampleTwo(books);

    }

    private static void exampleOne(List<Book> books) {
        Function<Book, Integer> fPrice = b -> b == null ? null : b.getPrice();
        Function<Book, String> fAuthor = b -> b == null ? null : b.getAuthor() == null ? null : b.getAuthor().getName();
        // Woks good with the Functions as Variables
        books.stream()
                .filter(b -> b == null || b.getDate().getYear() > 1990)
                .sorted(comparing(fPrice, nullsLast(naturalOrder()))
                        .thenComparing(fAuthor, nullsLast(reverseOrder()))
                )
                .forEach(System.out::println);

        // It doesn't work when I put the content of the Functions inline
        // Java says getPrice() cannot be find in java.lang.Object
        // it seems like comparing doesn't like the Lambda expression
//        books.stream()
//                .filter(b -> b == null || b.getDate().getYear() > 1990)
//                .sorted(comparing(b -> b == null ? null : b.getPrice(), nullsLast(naturalOrder()))
//                        .thenComparing(b -> b == null ? null : b.getAuthor() == null ? null : b.getAuthor().getName(), nullsLast(reverseOrder()))
//                )
//                .forEach(System.out::println);
    }

    private static void exampleTwo(List<Book> books) {
        // Other example using Optional

        Predicate<Book> fFilter = b -> Optional.ofNullable(b)
                .map(bb -> bb.getDate().getYear() > 1990)
                .orElse(false);

        Function<Book, Integer> fPrice2 = b -> Optional.ofNullable(b)
                .map(Book::getPrice)
                .orElse(null);

        Function<Book, String> fAuthor2 = b -> Optional.ofNullable(b)
                .map(Book::getAuthor)
                .map(Author::getName)
                .orElse(null);

        // This also works when I use the Predicate and Functions as variables
        books.stream()
                .filter(fFilter)
                .sorted(comparing(fPrice2, nullsLast(naturalOrder()))
                        .thenComparing(fAuthor2, nullsLast(reverseOrder()))
                )
                .forEach(System.out::println);

        // Same thing Here, not working when we replace the variables by their content of Lambda expression
//        books.stream()
//                .filter(b -> Optional.ofNullable(b)
//                        .map(bb -> bb.getDate().getYear() > 1990)
//                        .orElse(false))
//                .sorted(comparing(b -> Optional.ofNullable(b)
//                        .map(Book::getPrice)
//                        .orElse(null), nullsLast(naturalOrder()))
//                        .thenComparing(b -> Optional.ofNullable(b)
//                                .map(Book::getAuthor)
//                                .map(Author::getName)
//                                .orElse(null), nullsLast(reverseOrder()))
//                )
//                .forEach(System.out::println);
    }
}

共 (3) 个答案

  1. # 1 楼答案

    问题是泛型类型的解决方案。我不确定,但我认为这是thenComparing的签名,期待着Function<? super T, ...>。这意味着,“根”比较器绑定到某个“超级”T,即绑定到尽可能广泛的类型,即Object

    显式定义泛型类型也会使其可编译(参见Michal的anwser):

    .sorted(Comparator.<Book, Integer> comparing(b -> b.getPrice())
       .thenComparing(...))
    
  2. # 2 楼答案

    将变量类型化为Function<Book, Integer>时,编译器知道确切的泛型类型。内联版本中缺少此信息。指定显式类型参数会有帮助,如下所示:

    .sorted(
        Comparator.<Book, Integer> comparing( ...
    

    另见this答案

  3. # 3 楼答案

    IntellIj告诉bObject,而不是Book

    IntellIj error

    为了让它工作,将b转换为Book

    books.stream()
            .filter(b -> b == null || b.getDate().getYear() > 1990)
            .sorted(comparing((Book b) -> b == null ? null : b.getPrice(), nullsLast(naturalOrder()))
                    .thenComparing(b -> b == null ? null : b.getAuthor() == null ? null : b.getAuthor().getName(), nullsLast(reverseOrder()))
            )
            .forEach(System.out::println);
    

    第二部分也是如此