Teknologian jakaminen

Yksityiskohtainen selitys Java Stream API:sta: tehokas työkalu keräystietojen tehokkaaseen käsittelyyn

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

esittely

Java 8 sisältää monia uusia ominaisuuksia, joista merkittävimmät ovat Lambda-lausekkeet ja Stream API. Stream API tarjoaa tehokkaan ja tiiviin menetelmän keräystietojen käsittelyyn, mikä tekee koodista tiiviimmän ja selkeämmän, ja sillä on hyvä luettavuus ja ylläpidettävyys. Tässä artikkelissa käsitellään Java Stream API:n käyttöä, mukaan lukien peruskäsitteet, yleiset toiminnot, rinnakkaiskäsittely, käytännön tapaukset ja parhaat käytännöt.

Sisällysluettelo

  1. Mikä on Stream API
  2. Stream API:n perustoiminnot
  3. Stream API:n lisätoiminnot
  4. Rinnakkaisvirtaus
  5. Stream API käytännön tapaus
  6. Stream-sovellusliittymien parhaat käytännöt
  7. Usein kysytyt kysymykset ja ratkaisut
  8. Tee yhteenveto

Mikä on Stream API

Stream API on Java 8:ssa käyttöön otettu abstraktio kokoelmatietojen käsittelyyn, joka mahdollistaa tietojen käsittelyn deklaratiivisella tavalla (samanlailla kuin SQL-käskyt). Stream API tarjoaa monia tehokkaita toimintoja, joita voidaan käyttää kokoelmien suodattamiseen, lajitteluun, kartoittamiseen, vähentämiseen ja muihin toimiin, mikä yksinkertaistaa koodia huomattavasti.

ominaisuudet

  • deklaratiivinen ohjelmointi: Käytä Stream APIa koodin kirjoittamiseen deklaratiivisella tavalla, mikä vähentää vakiokoodia.
  • ketjupuhelu: Stream API:n toiminnot voidaan kutsua ketjuun, mikä parantaa koodin luettavuutta.
  • laiska arviointi: Välioperaatioita arvioidaan laiskasti ja ne arvioidaan vain, kun päätetoiminto suoritetaan.
  • rinnakkainen käsittely: Tukee rinnakkaiskäsittelyä ja voi hyödyntää täyden hyödyn moniytimisistä prosessoreista.

Stream API:n perustoiminnot

Luo stream

Stream-sovellusliittymä tarjoaa useita tapoja luoda Stream. Yleisiä ovat seuraavat:

  1. Luo kokoelmasta
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
  • 1
  • 2
  1. Luo taulukosta
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
  • 1
  • 2
  1. käyttääStream.of
Stream<String> stream = Stream.of("a", "b", "c");
  • 1
  1. käyttääStream.generate
Stream<Double> stream = Stream.generate(Math::random).limit(10);
  • 1
  1. käyttääStream.iterate
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(10);
  • 1

välioperaatiot

Välioperaatioita käytetään Streamin muuntamiseen, ja ne arvioidaan laiskasti Yleisiä välitoimintoja ovat seuraavat:

  1. filter: käytetään elementtien suodattamiseen.
Stream<String> stream = list.stream().filter(s -> s.startsWith("a"));
  • 1
  1. map: Käytetään yhdistämään jokainen elementti vastaavaan tulokseen.
Stream<String> stream = list.stream().map(String::toUpperCase);
  • 1
  1. flatMap: Käytetään jokaisen elementin muuntamiseen streamiksi ja yhdistämiseen yhdeksi streamiksi.
Stream<String> stream = list.stream().flatMap(s -> Stream.of(s.split("")));
  • 1
  1. distinct: Käytetään kaksoiskappaleiden poistamiseen.
Stream<String> stream = list.stream().distinct();
  • 1
  1. sorted: käytetään lajitteluun.
Stream<String> stream = list.stream().sorted();
  • 1
  1. peek: Käytetään jokaisen elementin tarkasteluun käsittelyn aikana.
Stream<String> stream = list.stream().peek(System.out::println);
  • 1

Terminaalin toiminta

Päätetoimintoja käytetään virran laskemiseen ja tulosten luomiseen. Yleisiä päätetoimintoja ovat seuraavat:

  1. forEach: Suorita toimenpide kullekin elementille.
list.stream().forEach(System.out::println);
  • 1
  1. collect: Muunna Stream muihin muotoihin.
List<String> result = list.stream().collect(Collectors.toList());
  • 1
  1. reduce: Pienennä streamin elementit arvoksi.
Optional<String> result = list.stream().reduce((s1, s2) -> s1 + s2);
  • 1
  1. toArray:Muunna stream taulukoksi.
String[] array = list.stream().toArray(String[]::new);
  • 1
  1. count: Laske elementtien määrä.
long count = list.stream().count();
  • 1
  1. anyMatchallMatchnoneMatch: Käytetään arvioinnin sovittamiseen.
boolean anyMatch = list.stream().anyMatch(s -> s.startsWith("a"));
boolean allMatch = list.stream().allMatch(s -> s.startsWith("a"));
boolean noneMatch = list.stream().noneMatch(s -> s.startsWith("a"));
  • 1
  • 2
  • 3
  1. findFirstfindAny: Käytetään elementtien etsimiseen.
Optional<String> first = list.stream().findFirst();
Optional<String> any = list.stream().findAny();
  • 1
  • 2

Stream API:n lisätoiminnot

järjestellä

käyttääsortedMenetelmä lajittelee virran ja voi kulkea vertailussa.

List<String> list = Arrays.asList("b", "c", "a");
List<String> sortedList = list.stream().sorted().collect(Collectors.toList());
// 逆序排序
List<String> sortedListDesc = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
  • 1
  • 2
  • 3
  • 4

suodattaa

käyttääfilterStreamin elementtien suodatusmenetelmä.

List<String> list = Arrays.asList("a", "b", "c");
List<String> filteredList = list.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList());
  • 1
  • 2

kartoitus

käyttäämapMenetelmä kartoittaa streamin elementit.

List<String> list = Arrays.asList("a", "b", "c");
List<String> mappedList = list.stream().map(String::toUpperCase).collect(Collectors.toList());
  • 1
  • 2

perussääntö

käyttääreduceMenetelmä streamin elementtien vähentämiseksi.

List<String> list = Arrays.asList("a", "b", "c");
String result = list.stream().reduce("", (s1, s2) -> s1 + s2);
  • 1
  • 2

kerätä

käyttääcollectMenetelmät muuntaa Streamin muihin muotoihin.

List<String> list = Arrays.asList("a", "b", "c");
List<String> collectedList = list.stream().collect(Collectors.toList());
Set<String> collectedSet = list.stream().collect(Collectors.toSet());
String joinedString = list.stream().collect(Collectors.joining(","));
  • 1
  • 2
  • 3
  • 4

Rinnakkaisvirtaus

Parallel Stream voi hyödyntää täysimääräisesti moniytimisprosessorien edut parantaakseen tietojenkäsittelyn tehokkuutta.voi käyttääparallelStreamMenetelmä luo rinnakkaisen virran.

List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.parallelStream().map(String::toUpperCase).collect(Collectors.toList());
  • 1
  • 2

Voidaan myös käyttääparallelMenetelmä muuntaa normaalin virran rinnakkaiseksi streamiksi.

List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.stream().parallel().map(String::toUpperCase).collect(Collectors.toList());
  • 1
  • 2

On huomattava, että rinnakkainen Stream ei aina ole nopeampi kuin sarjavirta, ja se on testattava tilanteen mukaan.

Stream API käytännön tapaus

Keräystietojen käsittely

Tapaus 1: Suodata ja muunna kokoelmia

Suodata merkkijonot, joiden pituus on pienempi kuin 3, ja muunna loput isoiksi kirjaimiksi.

List<String> list = Arrays.asList("a", "ab", "abc", "abcd");
List<String> result = list.stream()
    .filter(s -> s.length() >= 3)
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(result); // 输出:[ABC, ABCD]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Tapaus 2: Laske keskiarvo

Kun on annettu joukko kokonaislukuja, laske kaikkien kokonaislukujen keskiarvo.

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
OptionalDouble average = list.stream()
    .mapToInt(Integer::intValue)
    .average();
average.ifPresent(System.out::println); // 输出:3.0
  • 1
  • 2
  • 3
  • 4
  • 5

Tiedostotoiminnot

Tapaus 3: Lue tiedoston sisältö

Stream API:n käyttäminen

Lue tiedoston sisältö ja tulosta se konsoliin.

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {
    lines.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5
Tapaus 4: Laske sanan esiintymisten määrä

Lue tiedoston sisältö ja laske kunkin sanan esiintymismäärä.

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {
    Map<String, Long> wordCount = lines
        .flatMap(line -> Arrays.stream(line.split("\W+")))
        .collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()));
    wordCount.forEach((word, count) -> System.out.println(word + ": " + count));
} catch (IOException e) {
    e.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Tietokantatoiminnot

Tapaus 5: Tietokantakyselyn tulosten käsittely

Oletetaan, että meillä on tietokantataulukkousers, joka sisältää kenttiäidnamejaage . Voimme käyttää Stream API:ta kyselyn tulosten käsittelyyn.

List<User> users = queryDatabase();
List<String> names = users.stream()
    .filter(user -> user.getAge() > 18)
    .map(User::getName)
    .collect(Collectors.toList());
System.out.println(names);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Stream-sovellusliittymien parhaat käytännöt

  1. Vältä tarpeetonta rinnastusta: Parallel Stream ei ole aina nopeampi, ja se tulisi valita tapauskohtaisesti.
  2. Välitoimintojen ja terminaalitoimintojen oikea käyttö: Välioperaatioita arvioidaan laiskasti ja ne arvioidaan vain, kun päätetoiminto suoritetaan.
  3. Kiinnitä huomiota Streamin uudelleenkäytettävyyteen: Kun stream on kulutettu, sitä ei voi käyttää uudelleen. Jos sinun on käytettävä sitä uudelleen, voit harkita Streamin muuntamista kokoelmaksi ennen sen käyttöä.
  4. Käytä oikeaa keräilijääCollectorsLuokassa on erilaisia ​​keräilijöitä, joista voit valita sopivan keräilijän tarpeiden mukaan.
  5. Käsittele poikkeuksia: Stream APIa käytettäessä sinun on käsiteltävä mahdollisia poikkeuksia, erityisesti tiedostotoiminnoissa ja tietokantatoiminnoissa.

Usein kysytyt kysymykset ja ratkaisut

Streami on suljettu

Kun Stream on käytetty, sitä ei voi käyttää uudelleen. Jos sinun on käytettävä sitä uudelleen, voit harkita Streamin muuntamista kokoelmaksi ennen sen käyttöä.

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // 会抛出IllegalStateException
  • 1
  • 2
  • 3
  • 4

Suorituskykyongelmat

Rinnakkaisvirrat eivät aina ole nopeampia kuin sarjavirrat, ja ne on testattava tapauskohtaisesti.voi käyttääForkJoinPoolRinnakkaisvirran optimoimiseksi.

ForkJoinPool customThreadPool = new ForkJoinPool(4);
customThreadPool.submit(() ->
    list.parallelStream().forEach(System.out::println)
).get();
  • 1
  • 2
  • 3
  • 4

muistivuoto

Kun käytät Stream APIa suurten tietomäärien käsittelyyn, sinun on kiinnitettävä huomiota muistivuotojen ongelmaan.voi käyttääclosetapa sulkea Stream tai käyttäätry-with-resourceslauseke sulkee streamin automaattisesti.

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {
    lines.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5

Tee yhteenveto

Tässä artikkelissa esitellään yksityiskohtaisesti Java Stream API:n käyttö, mukaan lukien perustoiminnot, lisätoiminnot, rinnakkaiskäsittely, käytännön tapaukset ja parhaat käytännöt. Hyödyntämällä rationaalisesti Stream API:ta kehittäjät voivat yksinkertaistaa koodia huomattavasti, parantaa koodin luettavuutta ja ylläpidettävyyttä sekä parantaa tietojenkäsittelyn tehokkuutta. Toivon, että tästä artikkelista on apua Stream API:n käytössä Java-kehityksessä.

Java Stream API on tehokas työkalu keräystietojen käsittelyyn Eri toimintojen joustavan käytön avulla voidaan saavuttaa tehokas tietojenkäsittely ja suoratoistolaskenta. Jos et ole käyttänyt Stream API:ta, on suositeltavaa oppia ja hallita tämä tehokas työkalu mahdollisimman pian ja soveltaa sitä projektiisi kehitystehokkuuden ja koodin laadun parantamiseksi.