JavaRush /Blog Jawa /Random-JV /Pandhuan Jawa 8. 1 bagean.
ramhead
tingkat

Pandhuan Jawa 8. 1 bagean.

Diterbitake ing grup

"Jawa isih urip - lan wong wiwit ngerti."

Sugeng rawuh ing pitepanganku ing basa Jawa 8. Pandhuan iki bakal nggawa sampeyan langkah-langkah ing kabeh fitur anyar saka basa kasebut. Liwat conto kode sing ringkes lan prasaja, sampeyan bakal sinau carane nggunakake metode standar antarmuka , ekspresi lambda , metode referensi , lan anotasi sing bisa diulang . Ing pungkasan artikel, sampeyan bakal ngerti owah-owahan paling anyar kanggo API kayata stream, antarmuka fungsi, ekstensi asosiasi, lan API Tanggal anyar. Ora ana tembok teks sing mboseni - mung sawetara potongan kode sing dikomentari. Sekeca!

Cara standar kanggo antarmuka

Java 8 ngidini kita nambah cara non-abstrak sing diimplementasikake ing antarmuka kanthi nggunakake tembung kunci standar . Fitur iki uga dikenal minangka metode ekstensi . Punika conto pisanan kita: interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } Saliyane cara abstrak ngitung , antarmuka Formula uga nemtokake cara standar sqrt . Kelas sing ngetrapake antarmuka Formula mung ngleksanakake metode ngitung abstrak . Cara sqrt standar bisa digunakake langsung saka kothak. Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); } }; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0 Obyek rumus dileksanakake minangka obyek anonim. Kode cukup nyengsemaken: 6 baris kode kanggo mung ngetung sqrt(a * 100) . Kaya sing bakal kita deleng ing bagean sabanjure, ana cara sing luwih menarik kanggo ngetrapake obyek metode tunggal ing Jawa 8.

Ekspresi Lambda

Ayo dadi miwiti karo conto prasaja carane Ngurutake Uploaded strings ing versi awal Jawa: Metode helper statistik Collections.sort njupuk dhaftar lan Comparator kanggo Ngurutake unsur dhaftar diwenehi. Sing asring kedadeyan yaiku sampeyan nggawe komparator anonim lan menehi cara kanggo ngurutake. Tinimbang nggawe obyek anonim kabeh wektu, Jawa 8 menehi kemampuan kanggo nggunakake sintaks luwih kurang, lambda expressions : Nalika sampeyan bisa ndeleng, kode luwih cendhek lan luwih gampang diwaca. Nanging ing kene dadi luwih cendhek: Kanggo cara siji-baris, sampeyan bisa nyingkirake {} kurung kriting lan tembung kunci bali . Nanging ing kene kode dadi luwih cendhek: kompiler Jawa ngerti jinis paramèter, supaya sampeyan uga bisa ngilangi. Saiki ayo nyilem luwih jero babagan carane ekspresi lambda bisa digunakake ing urip nyata. List names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator () { @Override public int compare(String a, String b) { return b.compareTo(a); } }); Collections.sort(names, (String a, String b) -> { return b.compareTo(a); }); Collections.sort(names, (String a, String b) -> b.compareTo(a)); Collections.sort(names, (a, b) -> b.compareTo(a));

Antarmuka Fungsional

Kepiye ekspresi lambda pas karo sistem jinis Jawa? Saben lambda cocog karo jinis tartamtu sing ditetepake dening antarmuka. Lan antarmuka fungsional sing diarani kudu ngemot persis siji metode abstrak sing diumumake. Saben ekspresi lambda saka jinis tartamtu bakal cocog karo metode abstrak iki. Amarga metode standar dudu metode abstrak, sampeyan bebas nambah metode standar menyang antarmuka fungsional. Kita bisa nggunakake antarmuka kasepakatan minangka expression lambda, kasedhiya yen antarmuka ngandhut mung siji cara abstrak. Kanggo mesthekake yen antarmuka sampeyan nyukupi kondisi kasebut, sampeyan kudu nambah anotasi @FunctionalInterface . Compiler bakal informed dening anotasi iki antarmuka kudu ngemot mung siji cara, lan yen ketemu cara abstrak kapindho ing antarmuka iki, bakal uncalan kesalahan. Conto: Elinga yen kode iki uga bakal bener sanajan anotasi @FunctionalInterface durung diumumake. @FunctionalInterface interface Converter { T convert(F from); } Converter converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123

Referensi kanggo cara lan konstruktor

Conto ing ndhuwur bisa luwih disederhanakake kanthi nggunakake referensi metode statistik: Java 8 ngidini sampeyan ngirim referensi menyang metode lan konstruktor nggunakake :: simbol tembung kunci . Conto ing ndhuwur nuduhake carane cara statistik bisa digunakake. Nanging kita uga bisa referensi cara ing obyek: Ayo kang njupuk dipikir ing carane nggunakake :: dianggo kanggo konstruktor. Pisanan, ayo nemtokake conto karo konstruktor sing beda: Sabanjure, kita nemtokake antarmuka pabrik PersonFactory kanggo nggawe obyek wong anyar : Converter converter = Integer::valueOf; Integer converted = converter.convert("123"); System.out.println(converted); // 123 class Something { String startsWith(String s) { return String.valueOf(s.charAt(0)); } } Something something = new Something(); Converter converter = something::startsWith; String converted = converter.convert("Java"); System.out.println(converted); // "J" class Person { String firstName; String lastName; Person() {} Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } } interface PersonFactory

{ P create(String firstName, String lastName); } Tinimbang ngleksanakake pabrik kanthi manual, kita dasi kabeh bebarengan nggunakake referensi konstruktor: Kita nggawe referensi kanggo konstruktor kelas Person liwat Person :: new . Compiler Jawa bakal kanthi otomatis nelpon konstruktor cocok dening mbandhingaké teken saka konstruktor karo teken saka PersonFactory.create cara . PersonFactory personFactory = Person::new; Person person = personFactory.create("Peter", "Parker");

wilayah Lambda

Ngatur akses menyang variabel ruang lingkup njaba saka ekspresi lambda padha karo ngakses saka obyek anonim. Sampeyan bisa ngakses variabel pungkasan saka ruang lingkup lokal, uga lapangan conto lan variabel agregat.
Ngakses Variabel Lokal
Kita bisa maca variabel lokal kanthi modifier pungkasan saka ruang lingkup ekspresi lambda: Nanging ora kaya obyek anonim, variabel ora perlu diumumake final supaya bisa diakses saka ekspresi lambda . Kode iki uga bener: Nanging, variabel num kudu tetep immutable, i.e. dadi final implisit kanggo kompilasi kode. Kode ing ngisor iki ora bakal dikompilasi: Owah-owahan menyang num ing ekspresi lambda uga ora diidini. final int num = 1; Converter stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3 int num = 1; Converter stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3 int num = 1; Converter stringConverter = (from) -> String.valueOf(from + num); num = 3;
Ngakses Lapangan Kayata lan Variabel Statistik
Ora kaya variabel lokal, kita bisa maca lan ngowahi kolom conto lan variabel statistik ing ekspresi lambda. Kita ngerti prilaku iki saka obyek anonim. class Lambda4 { static int outerStaticNum; int outerNum; void testScopes() { Converter stringConverter1 = (from) -> { outerNum = 23; return String.valueOf(from); }; Converter stringConverter2 = (from) -> { outerStaticNum = 72; return String.valueOf(from); }; } }
Akses menyang cara standar antarmuka
Elinga conto karo conto rumus saka bagean pisanan? Antarmuka Formula nemtokake cara sqrt standar sing bisa diakses saka saben conto formula , kalebu obyek anonim. Iki ora bisa digunakake karo ekspresi lambda. Cara standar ora bisa diakses ing ekspresi lambda. Kode ing ngisor iki ora dikompilasi: Formula formula = (a) -> sqrt( a * 100);

Antarmuka fungsional sing dibangun

JDK 1.8 API ngemot akeh antarmuka fungsional sing dibangun. Sawetara iku uga dikenal saka versi Jawa sadurungé. Contone Comparator utawa Runnable . Antarmuka iki ditambahi kanggo nyakup dhukungan lambda nggunakake anotasi @FunctionalInterface . Nanging Java 8 API uga kebak antarmuka fungsi anyar sing bakal nggawe urip luwih gampang. Sawetara antarmuka kasebut kondhang saka perpustakaan Guava Google . Malah yen sampeyan wis menowo perpustakaan iki, sampeyan kudu njupuk dipikir nyedhaki carane antarmuka iki ditambahi, karo sawetara cara extension migunani.
Predikat
Predikat minangka fungsi Boolean kanthi siji argumen. Antarmuka ngemot macem-macem cara standar kanggo nggawe ekspresi logis kompleks (lan, utawa, negate) nggunakake predikat Predicate predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false Predicate nonNull = Objects::nonNull; Predicate isNull = Objects::isNull; Predicate isEmpty = String::isEmpty; Predicate isNotEmpty = isEmpty.negate();
Fungsi
Fungsi njupuk siji argumen lan ngasilake asil. Cara standar bisa digunakake kanggo nggabungake sawetara fungsi dadi siji ranté (nyipta, lan banjur). Function toInteger = Integer::valueOf; Function backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123"
Pemasok
Suppliers ngasilake asil (kayata) saka siji jinis utawa liyane. Ora kaya fungsi, panyedhiya ora njupuk bantahan. Supplier personSupplier = Person::new; personSupplier.get(); // new Person
Konsumen
Konsumen makili metode antarmuka kanthi argumen siji. Consumer greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker"));
Komparator
Comparator dikenal kanggo kita saka versi Jawa sadurungé. Java 8 ngidini sampeyan nambah macem-macem cara standar kanggo antarmuka. Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0
Opsional
Antarmuka Pilihan ora fungsional, nanging minangka sarana sing apik kanggo nyegah NullPointerException . Iki minangka titik penting kanggo bagean sabanjure, mula ayo goleki kanthi cepet babagan cara kerja antarmuka iki. Antarmuka Opsional minangka wadhah prasaja kanggo nilai sing bisa null utawa non-null. Mbayangno yen cara bisa ngasilake nilai utawa ora ana. Ing Jawa 8, tinimbang bali null , sampeyan ngasilake conto Opsional . Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0

Aliran

java.util.Stream minangka urutan unsur sing siji utawa akeh operasi ditindakake. Saben operasi Stream iku salah siji penengah utawa terminal. Operasi terminal ngasilake asil saka jinis tartamtu, nalika operasi penengah ngasilake obyek stream dhewe, saéngga chain of method calls bisa digawe. Stream minangka antarmuka, kaya java.util.Collection kanggo dhaptar lan set (peta ora didhukung). Saben operasi Stream bisa dileksanakake kanthi urutan utawa sejajar. Ayo goleki cara kerja stream. Pisanan, kita bakal nggawe kode sampel ing wangun dhaftar strings: Koleksi ing Jawa 8 ditingkatake supaya sampeyan bisa nggawe stream cukup mung dening nelpon Collection.stream () utawa Collection.parallelStream () . Bagean sabanjure bakal nerangake operasi stream sing paling penting lan prasaja. List stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1");
Nyaring
Filter nampa predikat kanggo nyaring kabeh unsur stream. Operasi iki minangka penengah, sing ngidini kita nelpon operasi stream liyane (contone kanggo Saben) ing asil (disaring). ForEach nampa operasi sing bakal ditindakake ing saben unsur aliran sing wis disaring. ForEach minangka operasi terminal. Kajaba iku, ora bisa nelpon operasi liyane. stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa2", "aaa1"
Diurut
Diurutake minangka operasi penengah sing ngasilake perwakilan aliran sing diurutake. Unsur diurutake kanthi urutan sing bener kajaba sampeyan nemtokake Comparator sampeyan . stringCollection .stream() .sorted() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa1", "aaa2" Elinga yen diurutake nggawe perwakilan stream sing diurutake tanpa mengaruhi koleksi kasebut dhewe. Urutan unsur stringCollection tetep ora kena: System.out.println(stringCollection); // ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1
peta
Operasi peta penengah ngowahi saben unsur menyang obyek liyane nggunakake fungsi asil. Conto ing ngisor iki ngowahi saben senar dadi senar gedhe. Nanging sampeyan uga bisa nggunakake peta kanggo ngowahi saben obyek menyang jinis sing beda. Jinis obyek stream sing diasilake gumantung saka jinis fungsi sing sampeyan tindakake menyang peta. stringCollection .stream() .map(String::toUpperCase) .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println); // "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"
cocog
Macem-macem operasi cocog bisa digunakake kanggo nyoba bebener predikat tartamtu ing hubungan stream. Kabeh operasi match minangka terminal lan ngasilake asil Boolean. boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a")); System.out.println(anyStartsWithA); // true boolean allStartsWithA = stringCollection .stream() .allMatch((s) -> s.startsWith("a")); System.out.println(allStartsWithA); // false boolean noneStartsWithZ = stringCollection .stream() .noneMatch((s) -> s.startsWith("z")); System.out.println(noneStartsWithZ); // true
Count
Count minangka operasi terminal sing ngasilake jumlah unsur stream minangka dawa . long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3
Ngurangi
Iki operasi terminal sing shortens unsur stream nggunakake fungsi liwati. Asil bakal dadi Opsional ngemot nilai shortened. Optional reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); // "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"

Aliran Paralel

Kaya sing kasebut ing ndhuwur, aliran bisa dadi sekuensial utawa paralel. Operasi stream sequential dileksanakake ing thread serial, nalika operasi stream podo dileksanakake ing sawetara Utas podo. Conto ing ngisor iki nuduhake carane gampang nambah kinerja nggunakake stream paralel. Pisanan, ayo nggawe dhaptar akeh unsur unik: Saiki kita bakal nemtokake wektu sing digunakake kanggo ngurutake aliran koleksi iki. int max = 1000000; List values = new ArrayList<>(max); for (int i = 0; i < max; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); }
Serial stream
long t0 = System.nanoTime(); long count = values.stream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("sequential sort took: %d ms", millis)); // sequential sort took: 899 ms
Aliran paralel
long t0 = System.nanoTime(); long count = values.parallelStream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis)); // parallel sort took: 472 ms Nalika sampeyan bisa ndeleng, loro pecahan meh padha, nanging ngurutake podo 50% luwih cepet. Kabeh sing perlu kanggo ngganti stream () kanggo parallelStream () .

peta

Kaya sing wis kasebut, peta ora ndhukung stream. Nanging, peta wiwit ndhukung cara anyar lan migunani kanggo ngrampungake masalah umum. Kode ing ndhuwur kudu intuisi: putIfAbsent ngelingake supaya ora nulis cek null tambahan. forEach nampa fungsi kanggo nglakokake saben nilai peta. Conto iki nuduhake carane operasi dileksanakake ing nilai peta nggunakake fungsi: Sabanjure, kita bakal sinau carane mbusak entri kanggo tombol tartamtu mung yen peta menyang nilai tartamtu: Cara liyane apik: Nggabungake entri peta cukup gampang: Gabung bakal salah siji nglebokake tombol / Nilai menyang peta, yen ora ana entri kanggo tombol diwenehi, utawa fungsi gabungan bakal disebut, kang bakal ngganti Nilai saka entri ana. Map map = new HashMap<>(); for (int i = 0; i < 10; i++) { map.putIfAbsent(i, "val" + i); } map.forEach((id, val) -> System.out.println(val)); map.computeIfPresent(3, (num, val) -> val + num); map.get(3); // val33 map.computeIfPresent(9, (num, val) -> null); map.containsKey(9); // false map.computeIfAbsent(23, num -> "val" + num); map.containsKey(23); // true map.computeIfAbsent(3, num -> "bam"); map.get(3); // val33 map.remove(3, "val3"); map.get(3); // val33 map.remove(3, "val33"); map.get(3); // null map.getOrDefault(42, "not found"); // not found map.merge(9, "val9", (value, newValue) -> value.concat(newValue)); map.get(9); // val9 map.merge(9, "concat", (value, newValue) -> value.concat(newValue)); map.get(9); // val9concat
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION