JavaRush /Блоги Java /Random-TG /Дастури Java 8. 1 қисм.
ramhead
Сатҳи

Дастури Java 8. 1 қисм.

Дар гурӯҳ нашр шудааст

"Ява ҳанӯз зинда аст ва одамон онро мефаҳманд."

Хуш омадед ба муаррифии ман бо Java 8. Ин дастур шуморо қадам ба қадам тамоми хусусиятҳои нави забонро меомӯзад. Тавассути мисолҳои кӯтоҳ ва оддии рамз, шумо мефаҳмед, ки чӣ тавр истифода бурдани усулҳои пешфарз интерфейс , ифодаҳои лямбда , усулҳои истинод ва шарҳҳои такроршавандаро истифода баред . Дар охири мақола, шумо бо тағиротҳои охирин ба APIҳо, аз қабor ҷараёнҳо, интерфейсҳои функсионалӣ, васеъшавии ассотсиатсияҳо ва API-и нави сана шинос хоҳед шуд. Деворҳои матни дилгиркунанда нест - танҳо як қатор пораҳои рамзи шарҳ додашуда. Баҳра баред!

Усулҳои пешфарз барои интерфейсҳо

Java 8 ба мо имкон медиҳад, ки усулҳои абстрактие, ки дар интерфейс тавассути истифодаи калимаи пешфарз татбиқ карда мешаванд, илова кунем . Ин хусусият инчунин ҳамчун усулҳои васеъ маълум аст . Ин аст мисоли аввалини мо: interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } Илова ба усули абстрактии ҳисоб , интерфейси Формула инчунин усули пешфарз sqrt -ро муайян мекунад . Синфҳое, ки интерфейси Формуларо амалӣ мекунанд, танҳо усули ҳисобкунии абстрактиро амалӣ мекунанд . Усули пешфарз sqrt метавонад бевосита аз қуттӣ истифода шавад. Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); } }; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0 Объекти формула ҳамчун an objectи номаълум амалӣ карда мешавад. Рамз хеле таъсирбахш аст: 6 сатри code барои ҳисоб кардани sqrt(a * 100) . Тавре ки мо дар боби оянда мебинем, роҳи ҷолибтар барои татбиқи an objectҳои усули ягона дар Java 8 вуҷуд дорад.

Ифодаҳои Ламбда

Биёед бо як мисоли оддии чӣ гуна ҷудо кардани массиви сатрҳо дар versionҳои аввали Java оғоз кунем: Усули ёвари оморӣ Collections.sort рӯйхат ва Муқоисакунандаро барои ҷудо кардани унсурҳои рӯйхати додашуда мегирад. Он чизе, ки аксар вақт рӯй медиҳад, ин аст, ки шумо муқоисакунандагони беном эҷод мекунед ва онҳоро ба усулҳои ҷудокунӣ интиқол медиҳед. Ба ҷои эҷоди an objectҳои номаълум ҳама вақт, Java 8 ба шумо имкон медиҳад, ки синтаксис, ифодаҳои лямбда камтар истифода баред : Тавре ки шумо мебинед, code хеле кӯтоҳтар ва хондан осонтар аст. Аммо дар ин ҷо он боз ҳам кӯтоҳтар мешавад: Барои усули як сатр, шумо метавонед аз қавсҳои ҷингила {} ва калимаи калидии return халос шавед . Аммо дар ин ҷо code боз ҳам кӯтоҳтар мешавад: компилятори Java аз намудҳои параметрҳо огоҳ аст, бинобар ин шумо метавонед онҳоро низ тарк кунед. Акнун биёед амиқтар бифаҳмем, ки чӣ гуна ифодаҳои ламбдаро дар ҳаёти воқеӣ истифода бурдан мумкин аст. 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));

Интерфейсҳои функсионалӣ

Чӣ тавр ифодаҳои лямбда ба системаи навъи Java мувофиқат мекунанд? Ҳар як ламбда ба навъи додашуда, ки бо интерфейс муайян шудааст, мувофиқат мекунад. Ва интерфейси ба ном функсионалӣ бояд маҳз як усули абстрактии эълоншударо дар бар гирад. Ҳар як ифодаи ламбдаи навъи додашуда ба ин усули абстрактӣ мувофиқ хоҳад буд.Азбаски усулҳои пешфарз усулҳои абстрактӣ нестанд, шумо озодед, ки усулҳои пешфарзро ба интерфейси функсионалии худ илова кунед. Мо метавонем интерфейси ихтиёриро ҳамчун ифодаи ламбда истифода барем, ба шарте ки интерфейс танҳо як усули абстрактиро дар бар гирад. Барои боварӣ ҳосил кардани он, ки интерфейси шумо ин шартҳоро қонеъ мекунад, шумо бояд шарҳи @FunctionalInterface -ро илова кунед . Тартибдиҳанда тавассути ин эзоҳ огоҳ карда мешавад, ки интерфейс бояд танҳо як усулро дар бар гирад ва агар дар ин интерфейс бо усули абстрактии дуюм дучор шавад, хатогӣ мекунад. Мисол: Дар хотир доред, ки ин code ҳатто агар шарҳи @FunctionalInterface эълон нашуда бошад ҳам, эътибор хоҳад дошт. @FunctionalInterface interface Converter { T convert(F from); } Converter converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123

Истинодҳо ба усулҳо ва конструкторҳо

Намунаи дар боло овардашударо бо истифода аз истинод ба усули оморӣ боз ҳам соддатар кардан мумкин аст: Java 8 ба шумо имкон медиҳад истинодҳоро ба усулҳо ва конструкторҳо бо истифода аз рамзҳои калидӣ :: интиқол диҳед . Мисоли боло нишон медиҳад, ки чӣ гуна усулҳои оморӣ истифода мешаванд. Аммо мо инчунин метавонем ба усулҳо оид ба an objectҳо муроҷиат кунем: Биёед бубинем, ки чӣ тавр истифодаи :: барои конструкторҳо кор мекунад. Аввалан, биёед як мисолро бо конструкторҳои гуногун муайян кунем: Минбаъд, мо интерфейси фабрикаи PersonFactory -ро барои эҷоди an objectҳои нави шахс муайян мекунем : 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); } Ба ҷои он ки заводро дастӣ иҷро кунем, мо ҳама чизро бо истифода аз истинод ба конструктор пайваст мекунем: Мо истинод ба созандаи синфи Person тавассути Person::new эҷод мекунем . Тартибдиҳандаи Java ба таври худкор созандаи мувофиқро бо муқоисаи имзои созандагон бо имзои усули PersonFactory.create даъват мекунад . PersonFactory personFactory = Person::new; Person person = personFactory.create("Peter", "Parker");

Минтақаи Ламбда

Ташкor дастрасӣ ба тағирёбандаҳои доираи берунӣ аз ифодаҳои лямбда ба дастрасӣ аз an objectи номаълум монанд аст. Шумо метавонед ба тағирёбандаҳои ниҳоӣ аз доираи маҳаллӣ, инчунин майдонҳои мисол ва тағирёбандаҳои ҷамъшуда дастрасӣ пайдо кунед.
Дастрасӣ ба тағирёбандаҳои маҳаллӣ
Мо метавонем як тағирёбандаи маҳаллиро бо тағирдиҳандаи ниҳоӣ аз доираи ифодаи лямбда хонем: Аммо бар хилофи an objectҳои беном, тағирёбандаҳо набояд ниҳоӣ эълон карда шаванд, то аз ифодаи лямбда дастрас бошанд . Ин рамз низ дуруст аст: Бо вуҷуди ин, тағирёбандаи num бояд тағирнопазир боқӣ монад, яъне. барои тартиб додани code ниҳоии ниҳоии бошад . Рамзи зерин тартиб дода намешавад: Тағирот ба num дар дохor ифодаи лямбда низ иҷозат дода намешавад. 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;
Дастрасӣ ба майдонҳои мисол ва тағирёбандаҳои оморӣ
Баръакси тағирёбандаҳои маҳаллӣ, мо метавонем майдонҳои мисол ва тағирёбандаҳои омориро дар дохor ифодаҳои лямбда хонем ва тағир диҳем. Мо ин рафторро аз an objectҳои номаълум медонем. 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); }; } }
Дастрасӣ ба усулҳои пешфарзи интерфейсҳо
Намунаро бо мисоли формулаи бахши аввал дар хотир доред? Интерфейси Формула усули пешфарзии sqrt- ро муайян мекунад , ки онро аз ҳар як мисоли формула , аз ҷумла an objectҳои беном дастрас кардан мумкин аст. Ин бо ифодаҳои лямбда кор намекунад. Усулҳои пешфарзро дар дохor ифодаҳои лямбда дастрас кардан мумкин нест. Рамзи зерин тартиб дода намешавад: Formula formula = (a) -> sqrt( a * 100);

Интерфейсҳои функсионалии дарунсохт

JDK 1.8 API дорои бисёр интерфейсҳои функсионалии дохилӣ мебошад. Баъзеи онҳо аз versionҳои қаблии Java маълуманд. Масалан, Comparator ё Runnable . Ин интерфейсҳо бо истифода аз шарҳи @FunctionalInterface дастгирии ламбдаро дар бар мегиранд . Аммо Java 8 API инчунин аз интерфейсҳои нави функсионалӣ пур аст, ки ҳаёти шуморо осонтар мекунанд. Баъзе аз ин интерфейсҳо аз китобхонаи Google Guava хуб маълуманд . Ҳатто агар шумо бо ин китобхона ошно бошед ҳам, шумо бояд бодиққат назар кунед, ки чӣ гуна ин интерфейсҳо бо баъзе усулҳои муфиди васеъшавӣ васеъ карда мешаванд.
Предикатхо
Предикатҳо функсияҳои булӣ бо як аргумент мебошанд. Интерфейс дорои усулҳои гуногуни пешфарз барои эҷоди ифодаҳои мураккаби мантиқӣ (ва, ё, рад кардан) бо истифода аз предикатҳо мебошад 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();
Функсияҳо
Функсияҳо як аргумент мегиранд ва натиҷа медиҳанд. Усулҳои пешфарзро барои муттаҳид кардани якчанд функсияҳо дар як занҷир истифода бурдан мумкин аст (таъсис ва сипас). Function toInteger = Integer::valueOf; Function backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123"
Таъминкунандагон
Таъминкунандагон натиҷа (мисол)-и ин ё он намудро бармегардонанд. Баръакси функсияҳо, провайдерҳо далелҳоро қабул намекунанд. Supplier personSupplier = Person::new; personSupplier.get(); // new Person
Истеъмолкунандагон
Истеъмолкунандагон усулҳои интерфейсро бо як далел муаррифӣ мекунанд. Consumer greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker"));
Муқоисакунандагон
Муқоисакунандагон ба мо аз versionҳои қаблии Java маълуманд. Java 8 ба шумо имкон медиҳад, ки усулҳои гуногуни пешфарзро ба интерфейсҳо илова кунед. 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
Опсияҳо
Интерфейси Optionals функсионалӣ нест, аммо он як утorтаи олӣ барои пешгирии NullPointerException аст . Ин як нуқтаи муҳим барои бахши оянда аст, бинобар ин биёед зуд ба он назар андозем, ки ин интерфейс чӣ гуна кор мекунад. Интерфейси ихтиёрӣ як контейнери оддӣ барои арзишҳоест, ки метавонанд сифр ё ғайринул бошанд. Тасаввур кунед, ки усул метавонад арзиш ё чизе баргардонад. Дар Java 8, ба ҷои баргардонидани null , шумо як мисоли ихтиёриро бармегардонед . 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

Ҷараён

java.util.Stream пайдарпаии элементҳост, ки дар онҳо як ё якчанд амалҳо иҷро мешаванд. Ҳар як амалиёти Stream ё мобайнӣ ё терминал аст. Амалиётҳои терминал натиҷаи як намуди мушаххасро бармегардонанд, дар ҳоле ки амалиёти мобайнӣ худи an objectи ҷараёнро бармегардонад ва имкон медиҳад, ки силсилаи зангҳои методӣ эҷод карда шавад. Stream интерфейсест, ба монанди java.util.Collection барои рӯйхатҳо ва маҷмӯаҳо (харитаҳо дастгирӣ намешаванд).Ҳар як амалиёти Stream метавонад пайдарпай ё мувозӣ иҷро карда шавад. Биёед бубинем, ки ҷараён чӣ гуна кор мекунад. Аввалан, мо рамзи намунаро дар шакли рӯйхати сатрҳо эҷод мекунем: Коллексияҳо дар Java 8 такмил дода шудаанд, то шумо метавонед ба таври оддӣ тавассути занг задан Collection.stream() ё Collection.parallelStream() ҷараёнҳо эҷод кунед . Дар фасли навбатӣ амалиёти ҷараёнҳои муҳимтарин ва содда шарҳ дода мешавад. 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");
Филтр
Филтр предикатҳоро барои филтр кардани ҳама унсурҳои ҷараён қабул мекунад. Ин амалиёт миёнарав аст, ки ба мо имкон медиҳад, ки амалиёти ҷараёнро (масалан forEach) дар натиҷаи натиҷа (филтршуда) даъват кунем. ForEach амалиётеро қабул мекунад, ки дар ҳар як унсури ҷараёни аллакай филтршуда иҷро карда мешавад. ForEach як амалиёти терминал аст. Ғайр аз он, даъват кардани амалиёти дигар ғайриимкон аст. stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa2", "aaa1"
Мураттаб
Мураттабшуда амалиёти фосилавӣ мебошад, ки намоиши мураттабшудаи ҷараёнро бармегардонад. Элементҳо бо тартиби дуруст мураттаб карда мешаванд, агар шумо Comparator -и худро муайян накунед . stringCollection .stream() .sorted() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa1", "aaa2" Дар хотир доред, ки sorted намоиши мураттабшудаи ҷараёнро бидуни таъсир ба худи коллексия эҷод мекунад. Тартиби элементҳои stringCollection бетағйир боқӣ мемонад: System.out.println(stringCollection); // ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1
Харита
Амали харитаи мобайнӣ бо истифода аз функсияи натиҷавӣ ҳар як элементро ба an objectи дигар табдил медиҳад. Мисоли зерин ҳар як сатрро ба сатри калон табдил медиҳад. Аммо шумо инчунин метавонед харитаро барои табдил додани ҳар як an object ба намуди дигар истифода баред. Навъи an objectҳои ҷараёни натиҷа аз намуди функсияе, ки шумо ба харита мегузаред, вобаста аст. stringCollection .stream() .map(String::toUpperCase) .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println); // "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"
Бозӣ
Барои санҷидани ҳақиқати як предикати мушаххас дар муносибати ҷараён, амалҳои гуногуни мувофиқро истифода бурдан мумкин аст. Ҳама амалиётҳои бозӣ терминал мебошанд ва натиҷаи мантиқиро бармегардонанд. 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
Ҳисоб
Ҳисоб як амалиёти терминалест, ки шумораи унсурҳои ҷараёнро ҳамчун дароз бар мегардонад . long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3
Кам кардан
Ин як амалиёти терминал аст, ки унсурҳои ҷараёнро бо истифода аз функсияи додашуда кӯтоҳ мекунад. Натиҷа ихтиёрӣ хоҳад буд , ки арзиши кӯтоҳшударо дар бар мегирад. Optional reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); // "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"

Ҷараёнҳои параллелӣ

Тавре ки дар боло зикр гардид, ҷараёнҳо метавонанд пайдарпай ё параллел бошанд. Амалиёти ҷараёни пайдарпай дар риштаи пайдарпай иҷро карда мешавад, дар ҳоле ки амалиёти ҷараёни параллелӣ дар якчанд риштаҳои параллелӣ иҷро карда мешаванд. Мисоли зерин нишон медиҳад, ки чӣ тавр ба осонӣ баланд бардоштани самаранокӣ бо истифода аз ҷараёни мувозӣ. Аввалан, биёед рӯйхати калони унсурҳои нодирро эҷод кунем: Ҳоло мо вақти ҷудо кардани ҷараёни ин коллексияро муайян мекунем. int max = 1000000; List values = new ArrayList<>(max); for (int i = 0; i < max; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); }
Ҷараёни силсилавӣ
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
Ҷараёни параллелӣ
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 Тавре ки шумо мебинед, ҳарду порчаҳо қариб якхелаанд, аммо ҷудокунии параллелӣ 50% тезтар аст. Ба шумо танҳо тағир додани stream() ба parallelStream() лозим аст .

Харита

Тавре ки аллакай зикр гардид, харитаҳо ҷараёнҳоро дастгирӣ намекунанд. Ба ҷои ин, харита усулҳои нав ва муфидро барои ҳалли мушкилоти умумӣ дастгирӣ кард. Рамзи дар боло зикршуда бояд беихтиёрона бошад: putIfAbsent моро аз навиштани чекҳои иловагӣ огоҳ мекунад. forEach функсияро барои иҷрои ҳар як арзиши харита қабул мекунад. Ин мисол нишон медиҳад, ки чӣ гуна амалиётҳо дар арзишҳои харита бо истифода аз функсияҳо иҷро карда мешаванд: Баъдан, мо мефаҳмем, ки чӣ гуна сабтро барои калиди додашуда танҳо агар он ба арзиши додашуда харита кунад, хориҷ кунем: Боз як усули хуб: Якҷоя кардани вурудоти харита хеле осон аст: Якҷоя кардан ё калид/арзишро ба харита дохил мекунад, агар барои калиди додашуда ягон вуруд мавҷуд набошад, ё функсияи якҷоякунӣ даъват карда мешавад, ки арзиши вуруди мавҷударо тағир медиҳад. 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
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION