java - software - jdk download for windows 10 64 bit




:: জাভা 8(ডবল কলোন) অপারেটর (11)

:: :: পদ্ধতি রেফারেন্স হিসাবে পরিচিত হয়। চলুন আমরা ক্লাস ক্রয়ের একটি ক্যালকুলেট প্রাইস পদ্ধতি কল করতে চাই। তারপর আমরা এটি লিখতে পারি:

Purchase::calculatePrice

এটি ল্যাম্বা এক্সপ্রেশন লেখার সংক্ষিপ্ত রূপ হিসাবেও দেখা যেতে পারে কারণ পদ্ধতির রেফারেন্সগুলি লম্বা এক্সপ্রেশনগুলিতে রূপান্তরিত হয়।

আমি জাভা 8 উত্স অন্বেষণ করছিলাম এবং কোডটির এই বিশেষ অংশটিকে খুব অবাক করে দিয়েছিলাম:

//defined in IntPipeline.java
@Override
public final OptionalInt reduce(IntBinaryOperator op) {
    return evaluate(ReduceOps.makeInt(op));
}

@Override
public final OptionalInt max() {
    return reduce(Math::max); //this is the gotcha line
}

//defined in Math.java
public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

Math::max একটি পদ্ধতি পয়েন্টার মত Math::max কিছু? কিভাবে একটি স্বাভাবিক static পদ্ধতি IntBinaryOperator রূপান্তর করা IntBinaryOperator ?


আমি এই উৎস খুব আকর্ষণীয় পাওয়া যায় নি।

আসলে, এটি একটি লম্বা যা একটি ডাবল কলোন পরিণত হয়। ডাবল কলোন আরও পঠনযোগ্য। আমরা ঐ পদক্ষেপগুলি অনুসরণ করি:

ধাপ 1:

// We create a comparator of two persons
Comparator c = (Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge());

ধাপ ২:

// We use the interference
Comparator c = (p1, p2) -> p1.getAge().compareTo(p2.getAge());

ধাপ 3:

// The magic
Comparator c = Comparator.comparing(Person::getAge());

এটা একটু দেরী মনে হচ্ছে কিন্তু এখানে আমার দুই সেন্ট। একটি lambda অভিব্যক্তি বেনামী পদ্ধতি তৈরি করতে ব্যবহৃত হয়। এটি কোনও বিদ্যমান পদ্ধতিতে কল করে না তবে এটি সরাসরি তার নামে পদ্ধতিটি উল্লেখ করা স্পষ্ট। এবং পদ্ধতি রেফারেন্স আমাদের পদ্ধতি-রেফারেন্স অপারেটর :: ব্যবহার করে তা করতে সক্ষম করে।

নিচের সহজ শ্রেণীটি বিবেচনা করুন যেখানে প্রত্যেক কর্মচারীর নাম এবং গ্রেড রয়েছে।

public class Employee {
    private String name;
    private String grade;

    public Employee(String name, String grade) {
        this.name = name;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }
}

ধরুন আমরা কিছু পদ্ধতির দ্বারা ফিরে আসা কর্মচারীদের একটি তালিকা আছে এবং আমরা তাদের গ্রেড দ্বারা কর্মচারীদের সাজানোর করতে চান। আমরা জানি যে আমরা বেনামী ক্লাসটি ব্যবহার করতে পারি:

    List<Employee> employeeList = getDummyEmployees();

    // Using anonymous class
    employeeList.sort(new Comparator<Employee>() {
           @Override
           public int compare(Employee e1, Employee e2) {
               return e1.getGrade().compareTo(e2.getGrade());
           }
    });

যেখানে getDummyEployee () এর মতো কিছু পদ্ধতি রয়েছে:

private static List<Employee> getDummyEmployees() {
        return Arrays.asList(new Employee("Carrie", "C"),
                new Employee("Farhan", "F"),
                new Employee("Brian", "B"),
                new Employee("Donald", "D"),
                new Employee("Adam", "A"),
                new Employee("Evan", "E")
                );
    }

এখন আমরা জানি যে Comparator একটি কার্যকরী ইন্টারফেস। একটি কার্যকরী ইন্টারফেস ঠিক এক বিমূর্ত পদ্ধতির সাথে (যদিও এটিতে এক বা একাধিক ডিফল্ট বা স্ট্যাটিক পদ্ধতি থাকতে পারে)। তাই আমরা ল্যাম্বা এক্সপ্রেশন ব্যবহার করতে পারি:

employeeList.sort((e1,e2) -> e1.getGrade().compareTo(e2.getGrade())); // lambda exp

এটা সব ভাল মনে হয় কিন্তু ক্লাস Employee অনুরূপ পদ্ধতি প্রদান করে তাহলে কি হবে:

public class Employee {
    private String name;
    private String grade;
    // getter and setter
    public static int compareByGrade(Employee e1, Employee e2) {
        return e1.grade.compareTo(e2.grade);
    }
}

এই ক্ষেত্রে পদ্ধতির নাম ব্যবহার করে নিজেই আরো স্পষ্ট হবে। অতএব আমরা পদ্ধতি রেফারেন্স ব্যবহার করে সরাসরি পদ্ধতিতে উল্লেখ করতে পারি:

employeeList.sort(Employee::compareByGrade); // method reference

ডক্স অনুসারে পদ্ধতির চারটি উল্লেখ রয়েছে:

+----+-------------------------------------------------------+--------------------------------------+
|    | Kind                                                  | Example                              |
+----+-------------------------------------------------------+--------------------------------------+
| 1  | Reference to a static method                          | ContainingClass::staticMethodName    |
+----+-------------------------------------------------------+--------------------------------------+
| 2  |Reference to an instance method of a particular object | containingObject::instanceMethodName | 
+----+-------------------------------------------------------+--------------------------------------+
| 3  | Reference to an instance method of an arbitrary object| ContainingType::methodName           |
|    | of a particular type                                  |                                      |  
+----+-------------------------------------------------------+--------------------------------------+
| 4  |Reference to a constructor                             | ClassName::new                       |
+------------------------------------------------------------+--------------------------------------+

জাভা -8 স্ট্রীমস রেডুসারে সহজ কাজগুলিতে একটি ফাংশন যা দুটি মানকে ইনপুট হিসাবে গ্রহণ করে এবং কিছু গণনার পরে ফলাফল দেয়। এই ফলাফল পরবর্তী পুনরাবৃত্তি খাওয়ানো হয়।

ম্যাথ ক্ষেত্রে: সর্বাধিক ফাংশন, পদ্ধতিটি সর্বাধিক দুটি মান ফেরত পাঠায় এবং শেষ পর্যন্ত আপনার হাতে সর্বাধিক সংখ্যা থাকে।


পুরানো জাভা সংস্করণগুলিতে, "::" বা লেম্বডের পরিবর্তে আপনি ব্যবহার করতে পারেন:

public interface Action {
    void execute();
}

public class ActionImpl implements Action {

    @Override
    public void execute() {
        System.out.println("execute with ActionImpl");
    }

}

public static void main(String[] args) {
    Action action = new Action() {
        @Override
        public void execute() {
            System.out.println("execute with anonymous class");
        }
    };
    action.execute();

    //or

    Action actionImpl = new ActionImpl();
    actionImpl.execute();
}

অথবা পদ্ধতি পাস:

public static void doSomething(Action action) {
    action.execute();
}

পূর্ববর্তী উত্তর কি সম্পর্কে সম্পূর্ণ সম্পূর্ণ :: পদ্ধতি রেফারেন্স আছে। সমষ্টিগতভাবে, এটি কার্যকর না করে একটি পদ্ধতি (বা কন্সট্রাকটর) উল্লেখ করার একটি উপায় সরবরাহ করে এবং মূল্যায়ন করার সময়, এটি কার্যক্ষম ইন্টারফেসের একটি উদাহরণ তৈরি করে যা লক্ষ্য টাইপ প্রসঙ্গ সরবরাহ করে।

ArrayList সর্বোচ্চ মান এবং কোনও :: পদ্ধতি রেফারেন্স ব্যবহার না করে একটি বস্তুর ArrayList জন্য দুটি উদাহরণ নীচে দেওয়া হল। ব্যাখ্যা নীচে মন্তব্য করা হয়।

ব্যবহার ছাড়া ::

import java.util.*;

class MyClass {
    private int val;
    MyClass (int v) { val = v; }
    int getVal() { return val; }
}

class ByVal implements Comparator<MyClass> {
    // no need to create this class when using method reference
    public int compare(MyClass source, MyClass ref) {
        return source.getVal() - ref.getVal();
    }
}

public class FindMaxInCol {
    public static void main(String args[]) {
        ArrayList<MyClass> myClassList = new ArrayList<MyClass>();
        myClassList.add(new MyClass(1));
        myClassList.add(new MyClass(0));
        myClassList.add(new MyClass(3));
        myClassList.add(new MyClass(6));

        MyClass maxValObj = Collections.max(myClassList, new ByVal());
    }
}

ব্যবহার সঙ্গে ::

import java.util.*;

class MyClass {
    private int val;
    MyClass (int v) { val = v; }
    int getVal() { return val; }
}

public class FindMaxInCol {
    static int compareMyClass(MyClass source, MyClass ref) {
        // This static method is compatible with the compare() method defined by Comparator. 
        // So there's no need to explicitly implement and create an instance of Comparator like the first example.
        return source.getVal() - ref.getVal();
    }

    public static void main(String args[]) {
        ArrayList<MyClass> myClassList = new ArrayList<MyClass>();
        myClassList.add(new MyClass(1));
        myClassList.add(new MyClass(0));
        myClassList.add(new MyClass(3));
        myClassList.add(new MyClass(6));

        MyClass maxValObj = Collections.max(myClassList, FindMaxInCol::compareMyClass);
    }
}

রানটাইমে তারা একই রকম আচরণ করে। বাইটকোড একই হতে পারে না (উপরের ক্ষেত্রে এটি একই বাইটকোড তৈরি করে (উপরের অভিযোগ এবং জাভা-সি চেক করুন))

রানটাইমে তারা ঠিক একই আচরণ করে। মেথড (গণিত :: সর্বোচ্চ) ;, এটি একই গণিত তৈরি করে (উপরে অভিযোগ এবং জাভা-সি চেক করুন))


সাধারণত, নিম্নরূপ Math.max(int, int) ব্যবহার করে reduce পদ্ধতি কল করবে:

reduce(new IntBinaryOperator() {
    int applyAsInt(int left, int right) {
        return Math.max(left, right);
    }
});

শুধু Math.max কলিং জন্য এটি অনেক সিনট্যাক্স প্রয়োজন। যেখানে Lambda এক্সপ্রেশন খেলা আসে। জাভা 8 থেকে এটি একই জিনিসটিকে খুব ছোট পথে ব্যবহার করার অনুমতি দেয়:

reduce((int left, int right) -> Math.max(left, right));

কিভাবে কাজ করে? জাভা কম্পাইলারটি "সনাক্ত করে", আপনি এমন একটি পদ্ধতি বাস্তবায়ন করতে চান যা দুটি int গুলি গ্রহণ করে এবং একটি int । এটি ইন্টারফেস IntBinaryOperator এক এবং একমাত্র পদ্ধতির প্রথাগত পরামিতির সমতুল্য (পদ্ধতির প্যারামিটারটি আপনি reduce চান)। সুতরাং কম্পাইলার আপনার জন্য বিশ্রাম দেয় - এটি অনুমান করে যে আপনি IntBinaryOperator প্রয়োগ করতে চান।

কিন্তু Math.max(int, int) নিজেই IntBinaryOperator এর আনুষ্ঠানিক প্রয়োজনীয়তা পূরণ করে, এটি সরাসরি ব্যবহার করা যেতে পারে। কারণ জাভা 7 এর কোনও সিনট্যাক্স নেই যা একটি পদ্ধতিকে একটি আর্গুমেন্ট হিসেবে পাস করতে দেয় (আপনি কেবল পদ্ধতি ফলাফল পাস করতে পারেন তবে পদ্ধতির রেফারেন্সগুলিও পাস করতে পারবেন না) :: বাক্য গঠন জাভা 8 এ রেফারেন্স পদ্ধতিতে উপস্থাপিত হয়েছিল:

reduce(Math::max);

উল্লেখ্য, এটি কম্পাইলার দ্বারা ব্যাখ্যা করা হবে, না RVM এ JVM দ্বারা! যদিও এটি তিনটি কোড স্নিপেটের জন্য বিভিন্ন বাইটকোড তৈরি করে, তবে সেগুলি সমানভাবে সমান হয়, তাই উপরের IntBinaryOperator সংক্ষিপ্ত (এবং সম্ভবত আরও কার্যকর) সংস্করণ হিসাবে বিবেচিত হতে পারে!

( ল্যামডা এক্সপ্রেশন অনুবাদ দেখুন)


:: জাভা 8 তে একটি নতুন অপারেটর অন্তর্ভুক্ত যা একটি বিদ্যমান শ্রেণীর একটি পদ্ধতি উল্লেখ করার জন্য ব্যবহৃত হয়। আপনি একটি শ্রেণীর স্ট্যাটিক পদ্ধতি এবং অ স্ট্যাটিক পদ্ধতি উল্লেখ করতে পারেন।

স্ট্যাটিক পদ্ধতি উল্লেখ করার জন্য, সিনট্যাক্স হল:

ClassName :: methodName 

অ স্ট্যাটিক পদ্ধতি উল্লেখ করার জন্য, সিনট্যাক্স হয়

objRef :: methodName

এবং

ClassName :: methodName

একটি পদ্ধতি উল্লেখ করার জন্য একমাত্র পূর্বশর্ত এমন পদ্ধতি যা একটি কার্যকরী ইন্টারফেসে বিদ্যমান, যা পদ্ধতি রেফারেন্সের সাথে সামঞ্জস্যপূর্ণ হতে হবে।

পদ্ধতি রেফারেন্স, যখন মূল্যায়ন, কার্যকরী ইন্টারফেস একটি উদাহরণ তৈরি।

পাওয়া যায়: http://www.speakingcs.com/2014/08/method-references-in-java-8.html


:: পদ্ধতি উল্লেখ বলা হয়। এটি মূলত একটি একক পদ্ধতির একটি রেফারেন্স। এটি একটি নাম দ্বারা বিদ্যমান পদ্ধতি বোঝায়।

সংক্ষিপ্ত ব্যাখ্যা :
নীচে একটি স্ট্যাটিক পদ্ধতির একটি রেফারেন্সের একটি উদাহরণ:

class Hey {
     public static double square(double num){
        return Math.pow(num, 2);
    }
}

Function<Double, Double> square = Hey::square;
double ans = square.apply(23d);

square বস্তু রেফারেন্স মত কাছাকাছি পাস করা এবং প্রয়োজন যখন ট্রিগার করা যেতে পারে। বস্তুত, static বেশী হিসাবে বস্তুর "স্বাভাবিক" পদ্ধতির রেফারেন্স হিসাবে এটি সহজেই ব্যবহার করা যেতে পারে। উদাহরণ স্বরূপ:

class Hey {
    public double square(double num) {
        return Math.pow(num, 2);
    }
}

Hey hey = new Hey();
Function<Double, Double> square = hey::square;
double ans = square.apply(23d);

উপরের Function একটি কার্যকরী ইন্টারফেস । সম্পূর্ণরূপে বোঝার :: , কার্যকরী ইন্টারফেসগুলি বোঝার জন্য এটি গুরুত্বপূর্ণ। সহজভাবে, একটি কার্যকরী ইন্টারফেস শুধুমাত্র একটি বিমূর্ত পদ্ধতি সঙ্গে একটি ইন্টারফেস।

কার্যক্ষম ইন্টারফেসগুলির উদাহরণগুলি Runnable , Callable এবং ActionListener

উপরে ফাংশন শুধুমাত্র একটি পদ্ধতি সঙ্গে একটি কার্যকরী ইন্টারফেস: apply । এটি একটি যুক্তি নেয় এবং একটি ফলাফল উত্পন্ন।

কেন কারণ :: অসাধারণ হয় that :

পদ্ধতির রেফারেন্সগুলি হল এক্সপ্রেশন যা ল্যাম্বা এক্সপ্রেশন (...) হিসাবে একই চিকিত্সা রয়েছে, কিন্তু পদ্ধতির শরীর সরবরাহ করার পরিবর্তে, তারা একটি বিদ্যমান পদ্ধতিটিকে নাম অনুসারে উল্লেখ করে।

যেমন lambda শরীরের পরিবর্তে

Function<Double, Double> square = (Double x) -> x * x;

আপনি কেবল করতে পারেন

Function<Double, Double> square = Hey::square;

রানটাইম এ, এই দুটি square পদ্ধতি একে অপরের হিসাবে ঠিক একই আচরণ। বাইটকোড একই হতে পারে বা হতে পারে না (যদিও, উপরের ক্ষেত্রে, একই বাইটকোড তৈরি করা হয়, উপরে কম্পাইল করুন এবং javap -c দিয়ে চেক করুন)।

সন্তুষ্টির একমাত্র প্রধান মানদণ্ড হল: আপনি যে পদ্ধতিটি অবজেক্ট রেফারেন্স হিসাবে ব্যবহার করেন তার কার্যকরী ইন্টারফেসের পদ্ধতিতে আপনার একই ধরণের স্বাক্ষর থাকা উচিত

নীচে অবৈধ:

Supplier<Boolean> p = Hey::square; // illegal

square একটি যুক্তি আশা এবং একটি double ফেরত। Supplier মধ্যে পদ্ধতি পদ্ধতি একটি যুক্তি আশা কিন্তু কিছু ফেরত না। সুতরাং, এই একটি ত্রুটি ফলাফল।

একটি পদ্ধতি রেফারেন্স একটি কার্যকরী ইন্টারফেস পদ্ধতি বোঝায়। (উল্লিখিত হিসাবে, কার্যকরী ইন্টারফেস প্রতিটি একমাত্র পদ্ধতি থাকতে পারে)।

আরো কিছু উদাহরণ: Consumer accept পদ্ধতিটি ইনপুট নেয় কিন্তু কিছু ফেরত দেয় না।

Consumer<Integer> b1 = System::exit;   // void exit(int status)
Consumer<String[]> b2 = Arrays::sort;  // void sort(Object[] a)
Consumer<String> b3 = MyProgram::main; // void main(String... args)

class Hey {
    public double getRandom() {
        return Math.random();
    }
}

Callable<Double> call = hey::getRandom;
Supplier<Double> call2 = hey::getRandom;
DoubleSupplier sup = hey::getRandom;
// Supplier is functional interface that takes no argument and gives a result

উপরে, getRandom কোন যুক্তি নেয় এবং একটি double ফেরত দেয়। সুতরাং যে কোনও কার্যকরী ইন্টারফেস যা মানদণ্ডকে সন্তুষ্ট করে: কোন যুক্তি গ্রহণ করবেন না এবং double ফেরত ব্যবহার করা যেতে পারে।

আরেকটি উদাহরণ:

Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("leo","bale","hanks"));
Predicate<String> pred = set::contains;
boolean exists = pred.test("leo");

পরামিতিযুক্ত ক্ষেত্রে ক্ষেত্রে :

class Param<T> {
    T elem;
    public T get() {
        return elem;
    }

    public void set(T elem) {
        this.elem = elem;
    }

    public static <E> E returnSame(E elem) {
        return elem;
    }
}

Supplier<Param<Integer>> obj = Param<Integer>::new;
Param<Integer> param = obj.get();
Consumer<Integer> c = param::set;
Supplier<Integer> s = param::get;

Function<String, String> func = Param::<String>returnSame;

পদ্ধতির রেফারেন্সগুলিতে বিভিন্ন শৈলী থাকতে পারে, তবে মৌলিকভাবে তারা একই জিনিসটি বোঝায় এবং সহজেই lambdas হিসাবে দৃশ্যমান হতে পারে:

  1. একটি স্ট্যাটিক পদ্ধতি ( ClassName::methName )
  2. একটি নির্দিষ্ট বস্তুর instanceRef::methName ( instanceRef::methName )
  3. একটি বিশেষ বস্তুর একটি সুপার পদ্ধতি ( super::methName )
  4. একটি বিশেষ ধরনের একটি শ্রেণীবিভক্ত বস্তুর একটি উদাহরণ পদ্ধতি ( ClassName::methName )
  5. একটি ক্লাস কনস্ট্রাকটর রেফারেন্স (ক্লাস ClassName::new )
  6. একটি অ্যারে কনস্ট্রাকটর রেফারেন্স ( TypeName[]::new )

আরও রেফারেন্সের জন্য, that


:: অপারেটর পদ্ধতি রেফারেন্সের জন্য জাভা 8 এ চালু করা হয়েছিল। একটি পদ্ধতি রেফারেন্স ল্যাম্বা অভিব্যক্তিটির জন্য শর্ট্যান্ড সিন্ট্যাক্স যা কেবল এক পদ্ধতি কার্যকর করে। এখানে একটি পদ্ধতির রেফারেন্সের সাধারণ সিনট্যাক্স রয়েছে:

Object :: methodName

আমরা জানি যে আমরা একটি বেনামী ক্লাস ব্যবহার করার পরিবর্তে lambda এক্সপ্রেশন ব্যবহার করতে পারি। কিন্তু কখনও কখনও, Lambda অভিব্যক্তি সত্যিই কিছু পদ্ধতির একটি কল, উদাহরণস্বরূপ:

Consumer<String> c = s -> System.out.println(s);

কোডটি পরিষ্কার করার জন্য, আপনি ল্যাম্বা এক্সপ্রেশনটিকে একটি পদ্ধতি রেফারেন্সে পরিণত করতে পারেন:

Consumer<String> c = System.out::println;







java-8