Я обнаружил, что декораторы и адаптеры время от времени полезны, так как я работал с приложениями на основе Java. Эти «обертки» хорошо работают в различных ситуациях и довольно просты для понимания и реализации, но все может стать немного сложнее, когда нужно обернуть иерархию объектов, а не один объект. В этой записи блога я расскажу о том, как потоки Java 8 облегчают преобразование между коллекциями объектов и коллекциями объектов, которые обертывают эти объекты.
Для этого обсуждения я применю два простых Java-класса, представляющих класс Movie и класс, который «оборачивает» этот класс с именем MovieWrapper . Класс Movie использовался в моем посте об улучшениях JDK 8 для коллекций Java. Класс Movie и класс, который его оборачивает, показаны далее.
Movie.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
package dustin.examples.jdk8.streams;import java.util.Objects;/** * Basic characteristics of a motion picture. * * @author Dustin */public class Movie{ /** Title of movie. */ private final String title; /** Year of movie's release. */ private final int yearReleased; /** Movie genre. */ private final Genre genre; /** MPAA Rating. */ private final MpaaRating mpaaRating; /** imdb.com Rating. */ private final int imdbTopRating; public Movie(final String newTitle, final int newYearReleased, final Genre newGenre, final MpaaRating newMpaaRating, final int newImdbTopRating) { this.title = newTitle; this.yearReleased = newYearReleased; this.genre = newGenre; this.mpaaRating = newMpaaRating; this.imdbTopRating = newImdbTopRating; } public String getTitle() { return this.title; } public int getYearReleased() { return this.yearReleased; } public Genre getGenre() { return this.genre; } public MpaaRating getMpaaRating() { return this.mpaaRating; } public int getImdbTopRating() { return this.imdbTopRating; } @Override public boolean equals(Object other) { if (!(other instanceof Movie)) { return false; } final Movie otherMovie = (Movie) other; return Objects.equals(this.title, otherMovie.title) && Objects.equals(this.yearReleased, otherMovie.yearReleased) && Objects.equals(this.genre, otherMovie.genre) && Objects.equals(this.mpaaRating, otherMovie.mpaaRating) && Objects.equals(this.imdbTopRating, otherMovie.imdbTopRating); } @Override public int hashCode() { return Objects.hash(this.title, this.yearReleased, this.genre, this.mpaaRating, this.imdbTopRating); } @Override public String toString() { return "Movie: " + this.title + " (" + this.yearReleased + "), " + this.genre + ", " + this.mpaaRating + ", " + this.imdbTopRating; }} |
MovieWrapper.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package dustin.examples.jdk8.streams;/** * Wraps a movie like a Decorator or Adapter might. * * @author Dustin */public class MovieWrapper{ private Movie wrappedMovie; public MovieWrapper(final Movie newMovie) { this.wrappedMovie = newMovie; } public Movie getWrappedMovie() { return this.wrappedMovie; } public void setWrappedMovie(final Movie newMovie) { this.wrappedMovie = newMovie; } public String getTitle() { return this.wrappedMovie.getTitle(); } public int getYearReleased() { return this.wrappedMovie.getYearReleased(); } public Genre getGenre() { return this.wrappedMovie.getGenre(); } public MpaaRating getMpaaRating() { return this.wrappedMovie.getMpaaRating(); } public int getImdbTopRating() { return this.wrappedMovie.getImdbTopRating(); } @Override public String toString() { return this.wrappedMovie.toString(); }} |
С классами Movie и MovieWrapper определенными выше, я теперь смотрю на преобразование коллекции одного из них в коллекцию другого. До JDK 8 типичный подход к преобразованию коллекции объектов Movie в коллекцию объектов MovieWrapper в MovieWrapper исходной коллекции объектов Movie и добавлении каждого из них в новую коллекцию объектов MovieWrapper . Это продемонстрировано в следующем листинге кода.
Преобразование коллекции обернутых объектов в коллекцию объектов-оберток
|
1
2
3
4
5
6
|
// movies previously defined as Set<Movie>final Set<MovieWrapper> wrappedMovies1 = new HashSet<>();for (final Movie movie : movies){ wrappedMovies1.add(new MovieWrapper(movie));} |
С потоками JDK 8 вышеприведенная операция теперь может быть реализована, как показано в следующем листинге кода.
Преобразование коллекции обернутых объектов в коллекцию объектов-обёрток — JDK 8
|
1
2
3
|
// movies previously defined as Set<Movie>final Set<MovieWrapper> wrappedMovies2 = movies.stream().map(movie -> new MovieWrapper(movie)).collect(Collectors.toSet()); |
Преобразование другого направления (из коллекции объектов-оболочек в коллекцию объектов-оболочек) можно сравнить аналогичным образом, чтобы продемонстрировать, как JDK 8 меняет это. Следующие два списка кода показывают старый путь и путь JDK 8.
Преобразование коллекции объектов-оболочек в коллекцию обернутых объектов
|
1
2
3
4
5
|
final Set<Movie> newMovies1 = new HashSet();for (final MovieWrapper wrappedMovie : wrappedMovies1){ newMovies1.add(wrappedMovie.getWrappedMovie());} |
Преобразование коллекции объектов-оболочек в коллекцию обернутых объектов — JDK 8
|
1
2
|
final Set<Movie> newMovies2 = wrappedMovies2.stream().map(MovieWrapper::getWrappedMovie).collect(Collectors.toSet()); |
Как и в некоторых примерах из моего поста « Потоковая функциональность коллекций» в JDK 8 , примеры в этом посте демонстрируют мощь агрегатных операций, представленных в JDK 8. Преимущества этих агрегатных операций по сравнению с традиционной итерацией включают в себя большую краткость в коде, возможно, (возможно, в конечном итоге) улучшенная читаемость и преимущества внутренней итерации (в том числе упрощение параллелизации с поддержкой потенциальных потоков ). Хороший пример использования потоков и более сложных функций для преобразования между коллекциями менее связанных объектов показан в объекте Transform в другой тип с Java 8 .
| Ссылка: | Использование потоков JDK 8 для преобразования коллекций обернутых объектов и коллекций объектов-оберток от нашего партнера по JCG Дастина Маркса в блоге Inspired by Actual Events . |