Interface de fonction en tant que lambda pour sortinger une collection?

J’étudie les expressions lambda et je ne parviens pas à utiliser java.util.function.Function pour sortinger une collection. Est-ce que quelqu’un pourrait m’aider ou me donner des indications sur la manière d’y parvenir?

J’ai un livre POJO et une classe qui stocke des livres dans une collection. J’essaie d’utiliser une expression lambda de l’interface Function pour renvoyer la même collection mais sortingée. Je pouvais utiliser Collections.sort () et le renvoyer de cette façon, mais je pensais qu’il y avait un moyen de le faire avec l’interface Function.

public class BookTable { private Map bookMap; public BookTable() { this.bookMap = new HashMap(); } public void addBook(Book book) { bookMap.put(size(), book); } public int size() { return bookMap.size(); } public List getRecord(int key) { return Collections.singletonList(bookMap.get(key)); } public List getRecordsWhere(Predicate predicate) { return bookMap.values() .stream() .filter(predicate) .collect(Collectors.toList()); } public List getSortedRecords(Function fieldExtractor) { // Return sorted list.... } } 

Livre POJO

 public class Book { private Ssortingng title; private Ssortingng author; public Ssortingng getTitle() { return title; } public void setTitle(Ssortingng title) { this.title = title; } public Ssortingng getAuthor() { return author; } public void setAuthor(Ssortingng author) { this.author = author; } } 

Juste un test rapide …

 public class BookTableTest { public static void main(Ssortingng[] 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))); } } 

Une partie de la valeur des stream consiste à ne pas réinventer toutes les méthodes de sorting, de filtrage et de collecte. Au lieu d’avoir une méthode de filtrage, une méthode de sorting, une méthode d’impression, etc., j’aurais simplement une méthode qui renvoie un Collection . Laissez l’appelant faire ce qu’il veut avec cette collection.

 public Collection getRecords() { return bookMap.values(); } ... table.getRecords().stream() .filter(book -> book.getAuthor().equals("Charles Dickens")) .sorted(Comparator.comparing(Book::getTitle)) .forEach(System.out::println); 

L’avantage de cette approche est qu’elle permet à l’utilisateur de chaîner les différentes opérations comme bon lui semble. Ils peuvent filtrer , sortinger et imprimer si c’est ce qu’ils veulent faire.

Voici une implémentation

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

où le Predicate et le Comparator peuvent être passés comme arguments pour getSortedRecords comme ci-dessous

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

Vous pouvez utiliser la méthode sortingée de stream. https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#sorted–

Je voulais une solution à l’aide de l’interface Function, mais la réponse de John Kugelman fait ressortir un très bon point … C’est la solution que j’ai finalement utilisée après quelques heures de recherche.

Comparable est un type générique, j’aurais donc dû le paramétrer mais cela n’a pas fonctionné.

Ce que j’essayais de faire:

 public List getSortedRecords(Function fieldExtractor) { return bookMap .values() .stream() .sorted(Comparator.comparing(fieldExtractor)) .collect(Collectors.toList()); } 

La méthode ne connaissait pas le type de champ à extraire du livre. La solution consistait à rendre la méthode elle-même générique:

 public > List getSortedRecords(Function fieldExtractor) { return bookMap .values() .stream() .sorted(Comparator.comparing(fieldExtractor)) .collect(Collectors.toList()); }