12 typowych sposobów korzystania ze strumieni Java
Źródło: Dev.to Interfejs API Java Streams pojawił się po raz pierwszy w Javie 8. Jego celem jest zapewnienie bardziej kompaktowego sposobu wykonywania typowych operacji na kolekcjach obiektów. Ponadto interfejs Java Streams API może służyć do implementowania złożonych algorytmów. W tym artykule omówimy typowe przypadki użycia strumieni Java. Najpierw wyjaśnijmy kilka podstaw:-
stream() - tworzy strumień z kolekcji.
-
Collect() - zbiera strumień do obiektu. Obiekt może być kolekcją, klasą pierwotną lub klasą niestandardową.
-
Collectors to klasa udostępniająca (wiele) statycznych metod zbierania strumieni.
1. Filtrowanie
-
Służy do usuwania wartości z kolekcji na podstawie warunku.
-
Aby filtrować elementy kolekcji na podstawie warunku, użyj metody filter() . Zapisywane są tylko pasujące elementy.
List<Integer> evenNumbers = originalList.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
2. Wstępne przetwarzanie
-
Przydatne, gdy każda wartość w kolekcji musi zostać zmieniona w miejscu.
-
Metoda map() służy do zastosowania funkcji do każdego elementu kolekcji i zwrócenia nowej kolekcji obliczonych wartości.
List<Integer> squares = originalList.stream()
.map(n -> n * n)
.collect(Collectors.toList());
3. Nawrócenie
-
Przydatne, gdy chcemy przekształcić kolekcję w inną kolekcję.
-
Można to osiągnąć na kilka sposobów.
Przykład 1: Utwórz mapę z list.
Konwertuj listę ciągów na mapę ciągów i długości.Map<String, Integer> wordLengths = words.stream()
.collect(Collectors.toMap(
word -> word,
word -> word.length()));
Przykład 2. Konwersja listy na zestawy.
Jest to częsty przypadek użycia do usuwania duplikatów. Dodatkowo, jeśli chcemy ponownie umieścić elementy na liście, możemy dwukrotnie skorzystać z metod stream() icollect () . Na przykład przekonwertujmy listę ciągów na listę unikalnych ciągów:// if we want to collect to a set
Set<String> uniqueWords = words.stream()
.collect(Collectors.toSet());
// OR
// if we want to start and end as a list
List<String> uniqueWords = words.stream()
.collect(Collectors.toSet()).stream().collect(Collectors.toList());
Przykład 3. Konwersja listy produktów na listę ich nazw. (Spłaszczenie - Wyrównanie)
List<String> productNames = products.stream()
.map(product -> product.getName())
.collect(Collectors.toList());
4. Redukcja
-
Zmniejsza kolekcję do pojedynczej wartości.
-
Metoda redukcji() służy do zastosowania funkcji do każdego elementu kolekcji i zwrócenia pojedynczej wartości.
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
5. Grupowanie
-
Grupuje elementy kolekcji na podstawie danego warunku.
-
Aby pogrupować elementy kolekcji według warunku, użyj metody Collectors.groupingBy() .
Map<String, List<Product>> productsByCategory = products.stream()
.collect(Collectors.groupingBy(product -> product.getCategory()));
6. Znalezienie
-
Wyszukuje pierwszy lub dowolny element kolekcji spełniający warunek.
-
Do wyszukiwania używane są metody findFirst() i findAny() .
Optional<String> firstLongWord = words.stream()
.filter(word -> word.length() > 5)
.findFirst();
// Note that findFirst() and findAny() methods return Optional<T> objects.
7. Sortowanie
-
Sortuje elementy kolekcji.
-
Do sortowania używana jest metoda sorted() .
List<Integer> topK = numbers.stream()
.sorted()
.limit(k)
.collect(Collectors.toList());
8. Partycjonowanie
-
Oddziela elementy kolekcji na podstawie danego warunku.
-
Do oddzielania elementów używana jest metoda Collectors.partitioningBy() .
Map<Boolean, List<Student>> passingFailing = students
.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
9. Liczenie
-
Zlicza liczbę elementów spełniających warunek.
-
Metoda count() służy do zliczania elementów spełniających warunek .
long count = words.stream()
.filter(word -> word.length() > 5)
.count();
10. Zasięg
-
Tworzy zakres wartości.
-
Aby utworzyć zakres wartości, użyj metody range() .
int[] numbers = IntStream.range(0, 10).toArray();
11. Dopasowanie
-
Dopasowuje elementy kolekcji do predykatu (warunku).
-
Metody takie jak anyMatch() , allMatch() i noneMatch() służą do dopasowywania elementów kolekcji do predykatu i zwracania wartości logicznej .
// true when all elements match the predicate
boolean allMatch = products.stream()
.allMatch(product -> product.getPrice() > 10);
// true when any element matches the predicate
boolean anyMatch = products.stream()
.anyMatch(product -> product.getPrice() > 10);
// true when no elements match the predicate
boolean noneMatch = products.stream()
.noneMatch(product -> product.getPrice() > 10);
12. Łączenie
-
Łączy elementy kolekcji w ciąg znaków.
-
Aby połączyć elementy kolekcji w ciąg znaków, użyj metody Collectors.joining() .
String joinedWords = words.stream()
.collect(Collectors.joining(" "));
To tyle, jeśli chodzi o ogólne scenariusze. Istnieją inne, mniej powszechne scenariusze, które możesz zbadać samodzielnie:
- Strumienie równoległe;
- Statystyka;
- Kolekcjonerzy niestandardowi.
Korzyści z wątków
-
Bardziej kompaktowy kod — zmniejsza ilość kodu wymaganego do przetworzenia kolekcji.
-
Mniej zmiennych pośrednich. Zmienne zakłócające mogą powodować wystąpienie błędów. Im ich mniej, tym łatwiej uniknąć nieoczekiwanych błędów.
-
Intuicyjny kod. Niektórzy programiści nie zgodzą się, że wątki są bardziej intuicyjne niż inne metody. Jednak gdy już się do nich przyzwyczaimy, stają się one znacznie bardziej intuicyjne niż inne metody.
Jak ocenić alokację pamięci obiektu w Javie
Źródło: DZone W tym artykule przedstawiono trzy najbardziej znane sposoby oceny alokacji pamięci obiektu w Javie.Ocena pamięci za pomocą Profilera
Najłatwiejszym sposobem oszacowania pamięci niektórych obiektów jest sprawdzenie bezpośrednio pamięci JVM za pomocą profilera, takiego jak Visual VM . Problem z tym podejściem polega na tym, że musisz połączyć się z działającą maszyną JVM, co może nie być możliwe w środowiskach produkcyjnych ze względów bezpieczeństwa.Ocena pamięci za pomocą instrumentów
Innym sposobem oszacowania przydzielonej pamięci dla danego obiektu jest użycie Instrumentów. Krótko mówiąc, musimy utworzyć klasę i skompilować ją do pliku JAR. Po utworzeniu pliku JAR musimy uruchomić naszą maszynę JVM wraz z tym plikiem JAR. Więcej o tej metodzie możesz dowiedzieć się tutaj . Wadą jest konieczność dodania określonego pliku jar do maszyny JVM, co może nie zostać zaakceptowane w produkcji ze względów bezpieczeństwa lub z pokrewnymi kwestiami.Ocena pamięci przy użyciu biblioteki JOL
Jako inną opcję możemy użyć JOL Library . Jest to bardzo potężna biblioteka, która może zapewnić szczegółowe oszacowanie wagi obiektu i pamięci przydzielonej przez instancję obiektu. Aby skorzystać z biblioteki musimy dodać zależność:<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
Następnie możemy go użyć w ten sposób:
out.println(GraphLayout.parseInstance(myObject).totalSize() / 1024000d + " MB")
ObjectSizeCalculator z archiwum Twittera
Publiczne repozytorium GitHub Twittera zawiera klasę narzędzi o nazwie ObjectSizeCalculator , która może oszacować przydzieloną pamięć dla danej instancji obiektu. Korzystanie z niego nie wymaga dużo pamięci ani czasu. Proces oceny zajmuje kilka sekund, nawet w przypadku dużych obiektów. Korzystanie z tej klasy jest dość proste:ObjectSizeCalculator.getObjectSize(address)
Polecam tę metodę, ale należy pamiętać, że jest obsługiwana tylko przez Java Hotspot, OpenJDK i TwitterJDK.
GO TO FULL VERSION