【问题标题】:java 8 stream filter list of object listsjava 8 对象列表的流过滤器列表
【发布时间】:2021-12-20 14:49:11
【问题描述】:

我想按对象字段过滤

List<Book> = Arrays.asList<book1, book2, book3>;

class Book {
    String author;
    List<Language>;
}

class Language {
    String locale;
    int code;
}

Book book1 = new Book("author1", Arrays.asList(new Language("en", 1), new Language("fr", 3)));
Book book2 = new Book("author2", Arrays.asList(new Language("ca", 2), new Language("fr", 3)));
Book book3 = new Book("author3", Arrays.asList(new Language("en", 1)));

我想要一个不包含语言 en 的书籍列表。

结果应该是:

List<Book> = Arrays.asList<book1, book2>;

Book book1 = new Book("author1", Arrays.asList(new Language("fr", 3)));
Book book2 = new Book("author2", Arrays.asList(new Language("ca", 2), new Language("fr", 3)));

我尝试这样做:但它没有从 book1 中删除 'en'

return books
        .stream()
        .filter(book -> book.getLanguages()
                .stream()
                .allMatch(value -> !"en".equals(value.getLanguage())))
        .collect(Collectors.toList());

【问题讨论】:

    标签: filter java-8 stream predicate


    【解决方案1】:

    首先您可以使用filter 来检查任何Language 对象的值为en,然后使用findFirst 来获取匹配的Language 对象

    return books.stream()
                .filter(book -> !book.getLanguages()
                      .stream()
                      .filter(value -> "en".equals(value.getLanguage()))
                      .findFirst().isPresent())
        .collect(Collectors.toList());
    

    【讨论】:

    • 这比 OP 已经在问题中发布的代码好多少?您只是以一种可读性较差的方式重写了 OP 的代码,而没有回答实际问题。
    【解决方案2】:

    您的问题有点令人困惑,但我从您的示例中了解到,有两个要求:

    1. 从每本书中过滤掉“en”语言
    2. 过滤掉只有“en”语言的书籍

    你可以像这样定义一个辅助方法:

    private Book removeLanguage(Book book, String locale) {
        List<Language> languages = book.getLanguages()
                                       .stream() 
                                       .filter(l -> !l.getLocale().equals(locale))
                                       .collect(Collectors.toList());
        
        // if all languages have been removed
        if(languages.isEmpty()) return null;
        // if no languages have been removed
        if(languages.size() == book.getLanguages().size()) return book;
        // return new book with filtered list of languages
        return new Book(book.getAuthor(), languages);
    }
    

    然后按如下方式使用:

    public List<Book> removeLanguage(List<Book> books, String locale) {
        return books.stream()
                    .map(b -> removeLanguage(b, locale))
                    .map(Objects::notNull)
                    .collect(Collectors.toList());
    }
    
    // ...
    
    List<Book> nonEnglishBooks = removeLanguage(books, "en");
    

    您确实可以将所有内容组合成一个链式管道。它会产生一些对象创建开销,但在少量数据上仍然表现良好:

    String localeToRemove = "en";
    
    List<Book> nonEnglishBooks = 
        books.stream()
             .map(b -> new Book(b.getAuthor(), 
                                b.getLanguages()
                                 .stream() 
                                 .filter(l -> !l.getLocale().equals(localeToRemove))
                                 .collect(Collectors.toList())
             .filter(b -> !b.getLanguages().isEmpty())
             .collect(Collectors.toList());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-03
      • 1970-01-01
      • 2017-06-21
      • 1970-01-01
      • 2021-11-06
      相关资源
      最近更新 更多