函数接口作为lambda来对集合进行排序?

时间:2016-09-01 02:13:09

标签: java lambda java-8

我正在研究lambda表达式,我正在努力研究如何使用java.util.function.Function对集合进行排序。有人可以帮助我,或者给我一些关于如何实现这个目标的指示?

我有一本书POJO和一个将书籍存储在一个集合中的类。我试图使用Function接口的lambda表达式返回相同的集合但已排序。我可以使用Collections.sort()并以这种方式返回它,但我认为有一种方法可以使用Function接口。

public class BookTable {

  private Map<Integer, Book> bookMap;

  public BookTable() {
      this.bookMap = new HashMap<>();
  }

  public void addBook(Book book) {
     bookMap.put(size(), book);
  }

  public int size() {
      return bookMap.size();
  }

  public List<Book> getRecord(int key) {
      return Collections.singletonList(bookMap.get(key));
  }

  public List<Book> getRecordsWhere(Predicate<Book> predicate) {
      return bookMap.values()
              .stream()
              .filter(predicate)
              .collect(Collectors.toList());
  }

  public List<Book> getSortedRecords(Function<Book, Comparable> fieldExtractor) {
      // Return sorted list....
  }
}

预订POJO

public class Book {

  private String title;
  private String author;

  public String getTitle() {
      return title;
  }

  public void setTitle(String title) {
      this.title = title;
  }

  public String getAuthor() {
      return author;
  }

  public void setAuthor(String author) {
     this.author = author;
  }
}

快速测试......

public class BookTableTest {

  public static void main(String[] args) {

      File file = new File("booklist.csv");
      BookTable table = new BookTable();

      Book book1 = new Book();
      book1.setAuthor("Author 1");
      book1.setTitle("Title 1");

      Book book2 = new Book();
      book2.setAuthor("Book 2 Author 1");
      book2.setTitle("Book 2 Title 1");

      Book book3 = new Book();
      book3.setAuthor("The best author");
      book3.setTitle("The best title");        

      table.addBook(book3);
      table.addBook(book1);
      table.addBook(book2);

      System.out.println("## Sorted by Title");
      System.out.println(table.printRecords(table.getSortedRecords(Book::getTitle)));

      System.out.println();
      System.out.println("## Sorted by Author");
      System.out.println(table.printRecords(table.getSortedRecords(Book::getAuthor)));

  }
}

4 个答案:

答案 0 :(得分:7)

流的部分价值不必重新发明所有的排序,过滤和收集方法。我没有过滤方法,排序方法,打印方法等,只需要一个返回Collection<Book>的方法。让呼叫者用该集合做他们想做的任何事情。

public Collection<Book> getRecords() {
    return bookMap.values();
}

...

table.getRecords().stream()
   .filter(book -> book.getAuthor().equals("Charles Dickens"))
   .sorted(Comparator.comparing(Book::getTitle))
   .forEach(System.out::println);

这种方法的优点在于它允许用户将他们喜欢的不同操作链接在一起。如果这是他们想要做的,他们可以过滤排序打印。

答案 1 :(得分:1)

这是一个实现

List<Book> getSortedRecords(Predicate<Book> predicate, Comparator<Book> comparator) {
    return this.bookMap.values().stream().filter(predicate).sorted(comparator).collect(Collectors.toList());
}

PredicateComparator可以作为getSortedRecords的参数传递,如下所示

getSortedRecords(b -> b != null, Comparator.comparing(Book::getTitle))

答案 2 :(得分:0)

答案 3 :(得分:0)

我想要一个使用Function接口的解决方案,但John Kugelman的回答非常有用....这是我经过几个小时研究后最终使用的解决方案。

Comparable是一个泛型类型,所以我应该对它进行参数化,但参数化它不起作用。

我想做的事情:

public List<Book> getSortedRecords(Function<Book, Comparable> fieldExtractor) {

    return bookMap
            .values()
            .stream()
            .sorted(Comparator.comparing(fieldExtractor))
            .collect(Collectors.toList());
}

该方法不知道将从书中提取的字段的类型。解决方案是使方法本身通用:

public <T extends Comparable<? super T>> List<Book> getSortedRecords(Function<Book, T> fieldExtractor) {

    return bookMap
            .values()
            .stream()
            .sorted(Comparator.comparing(fieldExtractor))
            .collect(Collectors.toList());
}