Почему потоковый фильтр не работает в приведенном ниже фрагменте кода - PullRequest
0 голосов
/ 16 октября 2018

Рассмотрим приведенный ниже фрагмент кода, и он дает null;Не могли бы вы помочь в этом:

//model class
public class Author {
    private String name;
    private int countOfBooks;
    // setters and getters left for brevity
}

//model class
public class Book {
    private String name;
    private int year;
    private Author author;
    // setters and getters left for brevity
}

Теперь, допустим, мы хотим отфильтровать книг, опубликованных в 2005 году или ранее. Мы бы, вероятно, filter в два раза:

// main class 
public static void main(String[] args) {
    List<Author> authors = Arrays.asList(new Author("Venkat", 10),new Author("Richord", 8));

    List<Book> books = Arrays.asList(new Book("Venkat", 2006, new Author()));

    books.stream()
         .filter(book -> book.getYear() > 2005)  // filter out books published in or before 2005
         .map(Book::getAuthor)                   // get the list of authors for the remaining books
         .filter(Objects::nonNull)               // remove null authors from the list
         .map(Author::getName)                   // get the list of names for the remaining authors
         .forEach(System.out::println);          // print the value of each remaining element
}

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

В примере, который вы пытаетесь использовать, намеревается напечатать имена авторов для книг с годом, превышающим 2005 год. Для этого требуются некоторые примеры данных - книги с разными годами (для фильтрации некоторых данных по годам) и авторы с именами.

Существует два класса: Author и Book.Давайте создадим некоторые примеры данных для них:


Авторы:

Автор имеет два атрибута - имя, количество книг.Давайте создадим два авторских объекта.Обратите внимание, что у авторов есть имена:

  • name = "HG Wells", количество книг = 2.
  • name = "Harper Lee", количество книг = 1.


Книги:

Книга имеет три атрибута - имя, год и автор.Давайте создадим три объекта книги:

  • name = "Война миров", год = 1898, author = "HG Wells" (автор создан выше: 1).
  • name= "Машина времени", год = 1895, author = "HG Wells" (автор создан выше: 1).
  • name = "Убить пересмешника", год = 1960, author = "Харпер Ли"(автор создан выше: 2).


Теперь создайте объекты Author:

Author hgWells = new Author("H. G. Wells", 2);
Author hLee = new Author("Harper Lee", 1);

ПРИМЕЧАНИЕ. Объект Author также может бытьпостроен с использованием следующего конструктора:

Author hgWells = new Author();

Это создает объект автора со значением имени как null и значением количества книг как zero.Эти null и zero являются значениями по умолчанию для переменных экземпляра, определенных в классе Author.Итак, вызов метода getName() возвращает null.


И некоторые Book объекты:

Book book1 = new Book("War of the Worlds", 1898, hgWells);
Book book2 = new Book("The Time Machine", 1895, hgWells);
Book book3 = new Book("To Kill a Mockingbird", 1960, hLee);


Создать список книг:

List<Book> books = Arrays.asList(book1, book2, book3);
System.out.println(books);

Будет напечатано:

[(War of the Worlds, 1898 - H. G. Wells), (The Time Machine, 1895 - H. G. Wells), (To Kill a Mockingbird, 1960 - Harper Lee)]

Обратите внимание, что переопределенный метод Object 'toString() показывает все подробности атрибутов объектов Book.


Фильтр книг:

Теперь у нас есть несколько книг с данными авторов, с которыми можно работать.Давайте отфильтруем их.В этом примере я буду печатать книги в 20-м веке (то есть фильтровать книги, изданные с годом, превышающим 1899, между 1900 и 1999 годами; у нас есть книги только с 19-го и 20-го века).

Поскольку мы используем потоки;фильтр должен быть лямбдаВот оно:

Predicate<Book> yearFilter = book -> book.getYear() > 1899;

Позволяет применить фильтр к списку книг:

books.stream()
    .filter(yearFilter)
    .map(book -> book.getAuthor().getName())
    .forEach(authorName -> System.out.println(authorName));

. Будет напечатано: Харпер Ли .Существует только одна книга с опубликованным годом в 20-м веке, где 1960 год и напечатано имя автора.

Комментарий:

Это примерсоздать тестовые данные и использовать их для работы с функцией фильтрации потока.


Код:

import java.util.*;
import java.util.stream.*;
import java.util.function.*;

class Author {

    private String name;
    private int bookCount;

    public Author() {
    }

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

    public String getName() {
        return name;
    }

    public int getBookCount() {
        return bookCount;
    }
}

class Book {

    private String name;
    private int year;
    private Author author;

    public Book(String name, int year, Author author) {
        this.name = name;
        this.year = year;
        this.author = author;
    }

    public String getName() {
        return name;
    }

    public int getYear() {
        return year;
    }

    public Author getAuthor() {
        return author;
    }

    @Override
    public String toString() {
        return "(" + name + ", " + year + " - " + author.getName() + ")";
    }

}

public class TestingLambdas2 {

    public static void main(String [] args) {

        Author hgWells = new Author("H. G. Wells", 2);
        Author hLee = new Author("Harper Lee", 1);

        Book book1 = new Book("War of the Worlds", 1898, hgWells);
        Book book2 = new Book("The Time Machine", 1895, hgWells);
        Book book3 = new Book("To Kill a Mockingbird", 1960, hLee);

        List<Book> books = Arrays.asList(book1, book2, book3);
        System.out.println("> All books:" + books);

        Predicate<Book> yearFilter = book -> book.getYear() > 1899;
        System.out.println("> Filtered book author(s):");
        books.stream()
                .filter(yearFilter)
                .map(book -> book.getAuthor().getName())
                .forEach(authorName -> System.out.println(authorName));
    }
}
0 голосов
/ 16 октября 2018

Если вы посмотрите на ваши условия на books.stream(), вы увидите, что есть определенное условие, когда вы получаете всех авторов для ваших книг:

.map(Book::getAuthor)              // get the list of authors for the remaining books

Однако в вашем объявлении books, вы объявили свою книгу так:

List<Book> books = Arrays.asList(
            new Book("Venkat",2006,new Author())
    );

Согласно объявлению вашего класса, это создаст книгу с названием "Venkat", год "2006".Для автора книги вы позвонили new Author() без параметров.Согласно объявлению вашего класса для автора, это создаст автора с нулевым именем и нулевым countOfBooks.

Вместо этого объявление вашей книги должно выглядеть примерно так:

List<Book> books = Arrays.asList(
            new Book("Venkat",2006,authors[0])
    );

ИЛИ

List<Book> books = Arrays.asList(
            new Book("Venkat",2006,new Author("Sekhar", 1))
    );
...