Mali by sme uzavrieť stream Java?
1. Prehľad
Po zavedení výrazov lambda v prostredí Java 8 je možné písať kód stručnejším a funkčnejším spôsobom. Prúdy a funkčné rozhrania sú jadrom tejto revolučnej zmeny na platforme Java.
V tomto rýchlom výučbe sa dozvieme, či by sme mali explicitne uzavrieť prúdy Java 8 tým, že sa na ne pozrieme z pohľadu zdrojov.
2. Uzatváranie prúdov
Streamy Java 8 implementujú Automatické uzatváranie rozhranie:
verejné rozhranie Stream rozširuje BaseStream {// vynechané} verejné rozhranie BaseStream rozširuje automatické uzatváranie {// vynechané}
Zjednodušene povedané, mali by sme myslieť na prúdy ako na zdroje, ktoré si môžeme požičať a vrátiť, keď s nimi skončíme. Na rozdiel od väčšiny zdrojov nemusíme vždy uzatvárať streamy.
Spočiatku to môže znieť protiintuitívne, takže sa pozrime, kedy by sme mali a kedy nemali uzatvárať streamy Java 8.
2.1. Kolekcie, polia a generátory
Väčšinou tvoríme Prúd inštancie zo zbierok Java, polí alebo funkcií generátora. Napríklad tu pracujeme na zbierke String prostredníctvom Stream API:
Zoznam farieb = List.of ("Červená", "Modrá", "Zelená") .stream () .filter (c -> c.length ()> 4) .map (String :: toUpperCase) .collect (Zberatelia. listovať());
Niekedy generujeme konečný alebo nekonečný sekvenčný prúd:
Random random = nový Random (); random.ints (). takeWhile (i -> i <1000) .forEach (System.out :: println);
Ďalej môžeme tiež použiť prúdy založené na poli:
Farba reťazca [] = {"Červená", "Modrá", "Zelená"}; Arrays.stream (farby). Mapa (String :: toUpperCase) .toArray ()
Pri narábaní s týmito druhmi prúdov by sme ich nemali výslovne uzatvárať. Jediným hodnotným zdrojom spojeným s týmito prúdmi je pamäť a o ňu sa automaticky stará Garbage Collection (GC).
2.2. Zdroje IO
Niektoré streamy sú však zálohované prostriedkami IO, ako sú súbory alebo sokety. Napríklad Files.lines () metóda streamuje všetky riadky pre daný súbor:
Files.lines (Paths.get ("/ path / to / file")) .flatMap (line -> Arrays.stream (line.split (","))) // vynechané
Pod kapotou táto metóda otvára a FileChannel inštancia a potom ju zatvorí po uzavretí streamu. Preto Ak zabudneme stream zavrieť, zostane otvorený základný kanál a potom by sme skončili s únikom zdrojov.
Aby sa zabránilo takýmto únikom zdrojov, dôrazne sa odporúča používať vyskúšajte zdroje idiom na zatvorenie streamov založených na IO:
try (Stream lines = Files.lines (Paths.get ("/ path / to / file"))) {lines.flatMap (line -> Arrays.stream (line.split (","))) // vynechané}
Týmto spôsobom kompilátor automaticky uzavrie kanál. Kľúčovým riešením je zavrieť všetky prúdy založené na vstupoch a výstupoch.
Upozorňujeme, že zatvorenie už uzavretého streamu by vyvolalo chybu IllegalStateException.
3. Záver
V tomto krátkom tutoriáli sme videli rozdiely medzi jednoduchými streammi a IO-heavy. Dozvedeli sme sa tiež, ako tieto rozdiely informujú naše rozhodnutie o tom, či uzavrieť alebo nezavrieť prúdy Java 8.
Ako obvykle je vzorový kód k dispozícii na GitHub.