JavaRush /Blog Java /Random-PL /Przerwa kawowa #108. 12 typowych zastosowań strumieni Jav...

Przerwa kawowa #108. 12 typowych zastosowań strumieni Java, jak ocenić alokację pamięci obiektu w Javie

Opublikowano w grupie Random-PL

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. Przerwa kawowa #108.  12 typowych zastosowań strumieni Java, jak ocenić alokację pamięci obiektu w Javie — 1Najpierw 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.

Przyjrzyjmy się teraz niektórym przypadkom użycia 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.

Przykład: usuń wszystkie liczby nieparzyste z listy.
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.

Na przykład przekonwertujmy każdą wartość na jej kwadrat.
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.

Jak wspomniano powyżej, możemy użyć metod map() icollect () do przekształcenia kolekcji w inną kolekcję.

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.

Należy pamiętać, że ponieważ metoda redukcji() zwraca pojedynczą wartość, nie można jej użyć do zwrócenia kolekcji. Przykład, sumujemy wszystkie wartości na liście:
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() .

Na przykład zgrupujmy wszystkie produkty w listy produktów według ich kategorii.
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() .

Zwykle przypomina to wyszukiwanie liniowe. Przykładowo szukamy pierwszego słowa na liście, którego długość przekracza 5 znaków.
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() .

Ogólnie rzecz biorąc, do sortowania kolekcji wystarczy funkcja Collections.sort() . Możemy użyć sorted() specjalnie, jeśli chcemy uruchomić inną operację. Na przykład posortujmy listę liczb w kolejności rosnącej, a następnie zwróćmy k pierwszych elementów.
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() .

Podział jest podobny do grupy, z tą różnicą, że zwraca dwie kolekcje — jedną dla elementów spełniających warunek, drugą dla elementów, które nie spełniają warunku. Podzielmy na przykład uczniów na tych, którzy zdali egzamin i tych, którzy go nie zdali.
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 .

Na przykład policzmy, ile słów na liście ma długość przekraczającą 5 znaków.
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() .

Istnieją specjalne klasy do tworzenia strumieni określonych typów - IntStream , LongStream , DoubleStream i Stream . Klasy te są przydatne podczas pracy z pierwotnymi typami liczbowymi. Aby przekonwertować tablicę na strumień, użyj Arrays.stream() . Utwórzmy na przykład tablicę liczb od 0 do 10.
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 .

Przykładowo sprawdźmy produkty z ceną wyższą niż 10.
// 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() .

Na przykład połączmy wszystkie słowa na liście w jeden ciąg.
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.

Dziękuję za przeczytanie. Mam nadzieję, że podobał Ci się ten artykuł. Istnieje wiele innych przypadków, w których można użyć wątków, które nie są omówione w tym temacie. Możesz dodać dowolny typowy scenariusz, który pominąłem.

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 . Przerwa kawowa #108.  12 typowych zastosowań strumieni Java, jak ocenić alokację pamięci obiektu w Javie — 2Problem 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.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION