JavaRush /Java Blog /Random-TK /Java-da funksional interfeýsler

Java-da funksional interfeýsler

Toparda çap edildi
Salam! Java Syntax Pro gözleginde lambda aňlatmalaryny öwrendik we olaryň funksional interfeýsden funksional usuly ýerine ýetirmekden başga zat däldigini aýtdyk. Başga sözler bilen aýdylanda, bu käbir näbelli (näbelli) synpyň durmuşa geçirilmegi, durmuşa geçirilmedik usuly. Eger-de kursyň leksiýalarynda lambda aňlatmalary bilen manipulýasiýa öwrenen bolsak, indi başga bir tarapy göz öňünde tutarys: ýagny bu interfeýsler. Java-yň sekizinji wersiýasy funksional interfeýsJava-da funksional interfeýsler - 1 düşünjesini girizdi . Bu näme? Bir ýerine ýetirilmedik (abstrakt) usuly bolan interfeýs işleýär. Köp sanly interfeýsler, meselem, öň ara alnyp maslahatlaşylan interfeýs ýaly bu kesgitlemäniň çägine girýär . Şeýle hem özümizi döredýän interfeýsler: Comparator
@FunctionalInterface
public interface Converter<T, N> {
   N convert(T t);
}
Bizde interfeýs bar, onuň wezipesi bir görnüşdäki obýektleri başga bir obýektlere (adapteriň bir görnüşine) öwürmek. Annotasiýa @FunctionalInterfacegaty çylşyrymly ýa-da möhüm zat däl, sebäbi maksady düzüjä bu interfeýsiň işleýändigini we birden köp usulyň bolmaly däldigini aýtmakdyr. Bu düşündirişli interfeýsde birden köp ýerine ýetirilmedik (abstrakt) usul bar bolsa, düzüji bu interfeýsi taşlamaz, sebäbi ýalňyş kod hökmünde kabul eder. Bu düşündirişsiz interfeýsler funksional hasap edilip bilner we işlär, ýöne @FunctionalInterfacebu goşmaça ätiýaçlandyryşdan başga zat däl. Geliň, klasa gaýdaly Comparator. Onuň koduna (ýa-da resminamalaryna ) seretseňiz , onuň birden köp usulynyň bardygyny görüp bilersiňiz. Soňra soraýarsyňyz: onda nädip funksional interfeýs hasaplap bolar? Abstrakt interfeýslerde ýekeje usulyň çäginde bolmadyk usullar bolup biler:
  • statik
Interfeýsler düşünjesi, berlen kod birliginiň haýsydyr bir usul ulanylyp bilinmejekdigini aňladýar. Javaöne Java 8-den başlap, interfeýslerde statiki we adaty usullary ulanmak mümkin boldy. Statik usullar gönüden-göni bir klasa bagly bolup, şeýle usuly çagyrmak üçin şol synpyň belli bir obýektini talap etmeýär. Theseagny, bu usullar interfeýs düşünjesine sazlaşykly gabat gelýär. Mysal hökmünde, öňki synpda null obýekti barlamak üçin statiki usul goşalyň:
@FunctionalInterface
public interface Converter<T, N> {

   N convert(T t);

   static <T> boolean isNotNull(T t){
       return t != null;
   }
}
Bu usuly alansoň, düzüji arz etmedi, bu biziň interfeýsimiziň henizem işleýändigini aňladýar.
  • esasy usullar
Java 8-den öň, beýleki synplara miras galan interfeýsde bir usul döretmeli bolsak, diňe her bir synpda durmuşa geçirilýän abstrakt usuly döredip bilerdik. Thisöne bu usul ähli synplar üçin birmeňzeş bolsa näme etmeli? Bu ýagdaýda abstrakt sapaklar köplenç ulanylýar . Javaöne Java 8-den başlap, ýerine ýetirilen usullar - deslapky usullar bilen interfeýsleri ulanmak mümkinçiligi bar. Interfeýsi miras alanyňyzda, bu usullary ýok edip ýa-da hemme zady bolşy ýaly goýup bilersiňiz (deslapky logikany goýuň). Adaty usul döredilende açar söz goşmaly - default:
@FunctionalInterface
public interface Converter<T, N> {

   N convert(T t);

   static <T> boolean isNotNull(T t){
       return t != null;
   }

   default void writeToConsole(T t) {
       System.out.println("Текущий an object - " + t.toString());
   }
}
Againene-de düzüjiniň arz edip başlamandygyny we funksional interfeýsiň çäklerinden çykmaýandygymyzy görýäris.
  • Obýekt synp usullary
Obýektleri deňeşdirmek leksiýasynda ähli synplaryň synpdan miras alýandygy hakda gürleşdik Object. Bu interfeýslere degişli däl. Theöne interfeýsde goluň synpyň käbir usuly bilen gabat gelýän abstrakt usuly bar bolsa Object, şeýle usul (ýa-da usullar) funksional interfeýs çäklendirmäni bozmaz:
@FunctionalInterface
public interface Converter<T, N> {

   N convert(T t);

   static <T> boolean isNotNull(T t){
       return t != null;
   }

   default void writeToConsole(T t) {
       System.out.println("Текущий an object - " + t.toString());
   }

   boolean equals(Object obj);
}
Againene-de düzüjimiz arz etmeýär, şonuň üçin interfeýs Converterhenizem işleýär. Indi sorag: näme üçin özümizi funksional interfeýsde ýerine ýetirilmedik bir usul bilen çäklendirmeli? Soň bolsa lambdalary ulanyp durmuşa geçirip bileris. Geliň, muňa mysal bilen seredeliň Converter. Munuň üçin synp döredeliň Dog:
public class Dog {
  String name;
  int age;
  int weight;

  public Dog(final String name, final int age, final int weight) {
     this.name = name;
     this.age = age;
     this.weight = weight;
  }
}
Şuňa meňzeş Raccoon(ýangyç):
public class Raccoon {
  String name;
  int age;
  int weight;

  public Raccoon(final String name, final int age, final int weight) {
     this.name = name;
     this.age = age;
     this.weight = weight;
  }
}
Bir obýektimiz bar diýsek Dog, meýdanlaryna esaslanyp bir obýekt döretmeli Raccoon. .Agny, Converterbir görnüşdäki obýekti beýlekisine öwürýär. Bu nähili bolar:
public static void main(String[] args) {
  Dog dog = new Dog("Bobbie", 5, 3);

  Converter<Dog, Raccoon> converter = x -> new Raccoon(x.name, x.age, x.weight);

  Raccoon raccoon = converter.convert(dog);

  System.out.println("Raccoon has parameters: name - " + raccoon.name + ", age - " + raccoon.age + ", weight - " + raccoon.weight);
}
Işledenimizde, konsola aşakdaky çykyşy alarys:

Raccoon has parameters: name - Bobbbie, age - 5, weight - 3
Bu bolsa usulymyzyň dogry işleýändigini aňladýar.Java-da funksional interfeýsler - 2

Esasy Java 8 Funksiýa interfeýsleri

Indi, geliň, Java 8-iň bize getiren we Stream API bilen bilelikde işjeň ulanylýan birnäçe funksional interfeýslerine seredeliň.

Predikat

Predicate- belli bir şertiň ýerine ýetirilendigini barlamak üçin işleýän interfeýs. Şert ýerine ýetirilen bolsa, gaýdyp geler true, ýogsam - false:
@FunctionalInterface
public interface Predicate<T> {
   boolean test(T t);
}
Mysal hökmünde, Predicatebirnäçe görnüşiň deňligini barlaýan bir döretmegi göz öňünde tutuň Integer:
public static void main(String[] args) {
   Predicate<Integer> isEvenNumber = x -> x % 2==0;

   System.out.println(isEvenNumber.test(4));
   System.out.println(isEvenNumber.test(3));
}
Konsol çykyşy:

true
false

Sarp ediji

Consumer(Iňlis dilinden - “sarp ediji”) - T görnüşli obýekti giriş argumenti hökmünde alýan, käbir hereketleri ýerine ýetirýän, ýöne hiç zat gaýtarmaýan funksional interfeýs:
@FunctionalInterface
public interface Consumer<T> {
   void accept(T t);
}
Mysal hökmünde, geçen setir argumenti bilen konsola salam bermek kimiň wezipesine serediň: Consumer
public static void main(String[] args) {
   Consumer<String> greetings = x -> System.out.println("Hello " + x + " !!!");
   greetings.accept("Elena");
}
Konsol çykyşy:

Hello Elena !!!

Üpjün ediji

Supplier(Iňlis dilinden - üpjün edijiden) - hiç hili argument almaýan, ýöne T görnüşindäki obýekti yzyna gaýtarýan funksional interfeýs:
@FunctionalInterface
public interface Supplier<T> {
   T get();
}
Mysal hökmünde Suppliersanawdan tötänleýin atlary çykarjakdygyna göz aýlaň:
public static void main(String[] args) {
   ArrayList<String> nameList = new ArrayList<>();
   nameList .add("Elena");
   nameList .add("John");
   nameList .add("Alex");
   nameList .add("Jim");
   nameList .add("Sara");

   Supplier<String> randomName = () -> {
       int value = (int)(Math.random() * nameList.size());
       return nameList.get(value);
   };

   System.out.println(randomName.get());
}
Muny işledip görsek, konsoldaky atlaryň sanawyndan tötänleýin netijeleri göreris.

Funksiýa

Function- bu funksional interfeýs T argumentini alýar we R görnüşindäki obýekte iberýär, netijede yzyna gaýtarylýar:
@FunctionalInterface
public interface Function<T, R> {
   R apply(T t);
}
Mysal hökmünde, sanlary setir formatyndan ( ) san formatyna ( ) öwürýän alalyň : FunctionStringInteger
public static void main(String[] args) {
   Function<String, Integer> valueConverter = x -> Integer.valueOf(x);
   System.out.println(valueConverter.apply("678"));
}
Işledenimizde, konsola aşakdaky çykyşy alarys:

678
PS: diňe sanlary däl, eýsem beýleki nyşanlary hem setire geçirsek, kadadan çykma - NumberFormatException.

UnaryOperator

UnaryOperator- T görnüşindäki obýekti parametr hökmünde alýan, üstünde birnäçe amallary ýerine ýetirýän we amallaryň netijesini T görnüşindäki obýekt görnüşinde yzyna gaýtarýan funksional interfeýs:
@FunctionalInterface
public interface UnaryOperator<T> {
   T apply(T t);
}
UnaryOperatorusulyny applysan inedördül görnüşinde ulanýar:
public static void main(String[] args) {
   UnaryOperator<Integer> squareValue = x -> x * x;
   System.out.println(squareValue.apply(9));
}
Konsol çykyşy:

81
Bäş sany funksional interfeýsine göz aýladyk. Java 8-den başlap, elýeterli zatlaryň hemmesi däl - bu esasy interfeýsler. Bar bolanlar, olaryň çylşyrymly analoglary. Doly sanawy resmi Oracle resminamalarynda tapyp bilersiňiz .

Akymdaky funksional interfeýsler

Aboveokarda aýdylyşy ýaly, bu funksional interfeýsler “Stream API” bilen berk baglanyşdyrylýar. Nädip soraýarsyňyz? Java-da funksional interfeýsler - 3Köp usullar Streambu funksional interfeýsler bilen ýörite işleýär. Funksiýa interfeýsleriniň nähili ulanylyp bilinjekdigine seredeliň Stream.

Predicate bilen usul

Mysal üçin, synp usulyny alalyň Stream- filterbu argument hökmünde kabul edilýär Predicatewe Streamdiňe şerti kanagatlandyrýan elementleri gaýtaryp berýär Predicate. -A kontekstinde , bu diňe interfeýs usulynda ulanylanda Streamyzyna gaýtarylýan elementlerden geçýändigini aňladýar . Ine, mysalymyzyň gözleýän görnüşi , ýöne elementleriň süzgüçi üçin : truetestPredicatePredicateStream
public static void main(String[] args) {
   List<Integer> evenNumbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8)
           .filter(x -> x % 2==0)
           .collect(Collectors.toList());
}
Netijede, sanaw evenNumbers{2, 4, 6, 8 elements elementlerinden ybarat bolar. Rememberadymyzda bolsa, collectähli elementleri belli bir kolleksiýa ýygnaýar: biziň ýagdaýymyzda List.

Sarp ediji bilen usul

StreamFunksiýa interfeýsini ulanýan usullaryň biri Consumer. Ine peek, mysalymyz şeýle bolar : ConsumerStream
public static void main(String[] args) {
   List<String> peopleGreetings = Stream.of("Elena", "John", "Alex", "Jim", "Sara")
           .peek(x -> System.out.println("Hello " + x + " !!!"))
           .collect(Collectors.toList());
}
Konsol çykyşy:

Hello Elena !!!
Hello John !!!
Hello Alex !!!
Hello Jim !!!
Hello Sara !!!
Methodöne bu usul peekbilen işleýänligi sebäpli Consumer, setirleriň üýtgemegi Streambolup geçmez, asyl elementleri bilen peekgaýdyp geler Stream: edil şonuň ýaly. Şonuň üçin sanaw peopleGreetings"enaelena", "Jon", "Alex", "Jim", "Sara" elementlerinden ybarat bolar. foreachUsula meňzeş, köplenç ulanylýan usul hem bar peek, ýöne tapawudy onuň ahyrky - terminal.

Üpjün ediji bilen usul

StreamFunksiýa interfeýsini ulanýan usulyň mysaly Supplier, generateoňa berlen funksional interfeýsiň esasynda çäksiz yzygiderliligi döredýär. SupplierKonsolda bäş sany tötänleýin at çap etmek üçin mysalymyzy ulanalyň :
public static void main(String[] args) {
   ArrayList<String> nameList = new ArrayList<>();
   nameList.add("Elena");
   nameList.add("John");
   nameList.add("Alex");
   nameList.add("Jim");
   nameList.add("Sara");

   Stream.generate(() -> {
       int value = (int) (Math.random() * nameList.size());
       return nameList.get(value);
   }).limit(5).forEach(System.out::println);
}
Konsolda alýan netijämiz:

John
Elena
Elena
Elena
Jim
limit(5)Bu ýerde usuly çäklendirmek üçin usuly ulandyk generate, ýogsam programma tötänleýin atlary konsola belli bir wagtlap çap ederdi.

Funksiýa usuly

StreamArgumentli usulyň adaty mysaly, bir görnüşiň elementlerini alýan, olar bilen bir zat edip, geçirýän Functionusuldyr , ýöne bular eýýäm başga görnüşiň elementleri bolup biler. mapMuňa mysal Functionbolup biler Stream:
public static void main(String[] args) {
   List<Integer> values = Stream.of("32", "43", "74", "54", "3")
           .map(x -> Integer.valueOf(x)).collect(Collectors.toList());
}
Netijede, sanlaryň sanawyny alýarys, ýöne Integer.

UnaryOperator bilen usul

Argument hökmünde ulanýan usul hökmünde UnaryOperator, synp usulyny alalyň Stream- iterate. Bu usul usula meňzeýär generate: ol çäksiz yzygiderliligi döredýär, ýöne iki delili bar:
  • birinjisi yzygiderliligiň başlanýan elementidir;
  • ikinjisi UnaryOperator, birinji elementden täze elementleri döretmek ýörelgesini görkezýär.
Ine, mysalymyzyň görnüşi UnaryOperator, ýöne usulda iterate:
public static void main(String[] args) {
   Stream.iterate(9, x -> x * x)
           .limit(4)
           .forEach(System.out::println);
}
Işledenimizde, konsola aşakdaky çykyşy alarys:

9
81
6561
43046721
.Agny, elementlerimiziň hersiniň özi köpelýär we ilkinji dört san üçin we ş.m. Java-da funksional interfeýsler - 4Bu hemmesi! Bu makalany okanyňyzdan soň Java-da Stream API-e düşünmek we özleşdirmek üçin bir ädim ýakynlaşsaňyz gowy bolardy!
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION