CodeGym /జావా బ్లాగ్ /యాదృచ్ఛికంగా /జావాలో లాంబ్డా వ్యక్తీకరణల వివరణ. ఉదాహరణలు మరియు పనులతో. ...
John Squirrels
స్థాయి
San Francisco

జావాలో లాంబ్డా వ్యక్తీకరణల వివరణ. ఉదాహరణలు మరియు పనులతో. పార్ట్ 2

సమూహంలో ప్రచురించబడింది
ఈ వ్యాసం ఎవరి కోసం?
  • ఇది ఈ వ్యాసం యొక్క మొదటి భాగాన్ని చదివిన వ్యక్తుల కోసం ;
  • ఇది ఇప్పటికే జావా కోర్ గురించి బాగా తెలుసని భావించే వ్యక్తుల కోసం, కానీ జావాలో లాంబ్డా ఎక్స్‌ప్రెషన్‌ల గురించి ఎటువంటి క్లూ లేదు. లేదా లాంబ్డా వ్యక్తీకరణల గురించి వారు ఏదైనా విన్నారు, కానీ వివరాలు లేవు.
  • లాంబ్డా ఎక్స్‌ప్రెషన్‌ల గురించి కొంత అవగాహన ఉన్న, కానీ ఇప్పటికీ వాటిని చూసి భయపడి, వాటిని ఉపయోగించడం అలవాటు లేని వ్యక్తుల కోసం ఇది.
మీరు ఈ వర్గాలలో ఒకదానికి సరిపోకపోతే, మీరు ఈ కథనాన్ని బోరింగ్‌గా, లోపభూయిష్టంగా లేదా సాధారణంగా మీ కప్పు టీ కాకపోవచ్చు. ఈ సందర్భంలో, ఇతర విషయాలకు వెళ్లడానికి సంకోచించకండి లేదా, మీరు ఈ అంశంపై బాగా ప్రావీణ్యం కలిగి ఉన్నట్లయితే, దయచేసి నేను కథనాన్ని ఎలా మెరుగుపరచవచ్చు లేదా అనుబంధించవచ్చు అనే దానిపై వ్యాఖ్యలలో సూచనలు చేయండి. జావాలో లాంబ్డా వ్యక్తీకరణల వివరణ.  ఉదాహరణలు మరియు పనులతో.  పార్ట్ 2 - 1మెటీరియల్ ఏ విద్యాసంబంధమైన విలువను కలిగి ఉండదు, కొత్తదనాన్ని విడనాడదు. చాలా విరుద్ధంగా: నేను సంక్లిష్టమైన (కొంతమంది వ్యక్తులకు) వీలైనంత సరళంగా వివరించడానికి ప్రయత్నిస్తాను. స్ట్రీమ్ APIని వివరించమని చేసిన అభ్యర్థన దీన్ని వ్రాయడానికి నన్ను ప్రేరేపించింది. నేను దాని గురించి ఆలోచించాను మరియు లాంబ్డా వ్యక్తీకరణల గురించి అవగాహన లేకుండా నా స్ట్రీమ్ ఉదాహరణలు కొన్ని అర్థం చేసుకోలేవని నిర్ణయించుకున్నాను. కాబట్టి మేము లాంబ్డా వ్యక్తీకరణలతో ప్రారంభిస్తాము.

బాహ్య వేరియబుల్స్ యాక్సెస్

ఈ కోడ్ అనామక తరగతితో కంపైల్ చేస్తుందా?

int counter = 0;
Runnable r = new Runnable() { 

    @Override 
    public void run() { 
        counter++;
    }
};
సంఖ్య. counter వేరియబుల్ తప్పనిసరిగా ఉండాలి final. లేదా కాకపోతే final, కనీసం దాని విలువను మార్చలేరు. అదే సూత్రం లాంబ్డా వ్యక్తీకరణలకు వర్తిస్తుంది. వారు ప్రకటించబడిన స్థలం నుండి వారు "చూడగల" అన్ని వేరియబుల్స్‌ను యాక్సెస్ చేయగలరు. కానీ లాంబ్డా వాటిని మార్చకూడదు (వాటికి కొత్త విలువను కేటాయించండి). అయితే, అనామక తరగతుల్లో ఈ పరిమితిని దాటవేయడానికి ఒక మార్గం ఉంది. రిఫరెన్స్ వేరియబుల్‌ని సృష్టించండి మరియు వస్తువు యొక్క అంతర్గత స్థితిని మార్చండి. అలా చేయడం వలన, వేరియబుల్ కూడా మారదు (ఒకే వస్తువుకు పాయింట్లు) మరియు సురక్షితంగా final.

final AtomicInteger counter = new AtomicInteger(0);
Runnable r = new Runnable() { 

    @Override
    public void run() {
        counter.incrementAndGet();
    }
};
ఇక్కడ మన counterవేరియబుల్ ఒక వస్తువుకు సూచన AtomicInteger. మరియు incrementAndGet()ఈ వస్తువు యొక్క స్థితిని మార్చడానికి పద్ధతి ఉపయోగించబడుతుంది. ప్రోగ్రామ్ నడుస్తున్నప్పుడు వేరియబుల్ విలువ మారదు. ఇది ఎల్లప్పుడూ ఒకే వస్తువును సూచిస్తుంది, ఇది చివరి కీవర్డ్‌తో వేరియబుల్‌ను ప్రకటించడానికి అనుమతిస్తుంది. ఇక్కడ అదే ఉదాహరణలు ఉన్నాయి, కానీ లాంబ్డా వ్యక్తీకరణలతో:

int counter = 0;
Runnable r = () -> counter++;
ఇది అనామక తరగతితో ఉన్న సంస్కరణ వలె అదే కారణంతో కంపైల్ చేయబడదు:  counterప్రోగ్రామ్ నడుస్తున్నప్పుడు మార్చకూడదు. కానీ మనం ఇలా చేస్తే అంతా బాగుంటుంది:

final AtomicInteger counter = new AtomicInteger(0); 
Runnable r = () -> counter.incrementAndGet();
ఇది కాలింగ్ పద్ధతులకు కూడా వర్తిస్తుంది. లాంబ్డా ఎక్స్‌ప్రెషన్‌లలో, మీరు అన్ని "కనిపించే" వేరియబుల్స్‌ను యాక్సెస్ చేయడమే కాకుండా, ఏవైనా యాక్సెస్ చేయగల పద్ధతులను కూడా కాల్ చేయవచ్చు.

public class Main { 

    public static void main(String[] args) {
        Runnable runnable = () -> staticMethod();
        new Thread(runnable).start();
    } 

    private static void staticMethod() { 

        System.out.println("I'm staticMethod(), and someone just called me!");
    }
}
ప్రైవేట్ అయినప్పటికీ staticMethod(), ఇది main()పద్ధతి లోపల అందుబాటులో ఉంటుంది, కాబట్టి దీనిని పద్ధతిలో సృష్టించబడిన లాంబ్డా లోపల నుండి కూడా పిలుస్తారు main.

లాంబ్డా వ్యక్తీకరణ ఎప్పుడు అమలు చేయబడుతుంది?

మీరు ఈ క్రింది ప్రశ్న చాలా సరళంగా ఉండవచ్చు, కానీ మీరు దానిని అదే విధంగా అడగాలి: లాంబ్డా వ్యక్తీకరణ లోపల కోడ్ ఎప్పుడు అమలు చేయబడుతుంది? ఇది ఎప్పుడు సృష్టించబడుతుంది? లేదా దీనిని పిలిచినప్పుడు (ఇది ఇంకా తెలియదు)? దీన్ని తనిఖీ చేయడం చాలా సులభం.

System.out.println("Program start"); 

// All sorts of code here
// ...

System.out.println("Before lambda declaration");

Runnable runnable = () -> System.out.println("I'm a lambda!");

System.out.println("After lambda declaration"); 

// All sorts of other code here
// ...

System.out.println("Before passing the lambda to the thread");
new Thread(runnable).start(); 
స్క్రీన్ అవుట్‌పుట్:

Program start
Before lambda declaration
After lambda declaration
Before passing the lambda to the thread
I'm a lambda!
థ్రెడ్ సృష్టించబడిన తర్వాత మరియు ప్రోగ్రామ్ యొక్క అమలు పద్ధతికి చేరుకున్నప్పుడు మాత్రమే లాంబ్డా వ్యక్తీకరణ చివరిలో అమలు చేయబడిందని మీరు చూడవచ్చు run(). ఇది ప్రకటించబడినప్పుడు ఖచ్చితంగా కాదు. Runnableలాంబ్డా వ్యక్తీకరణను ప్రకటించడం ద్వారా, మేము ఒక వస్తువును మాత్రమే సృష్టించాము మరియు దాని run()పద్ధతి ఎలా ప్రవర్తిస్తుందో వివరించాము. పద్ధతి చాలా తరువాత అమలు చేయబడుతుంది.

పద్ధతి సూచనలు?

మెథడ్ రిఫరెన్స్‌లు లాంబ్డాస్‌తో నేరుగా సంబంధం కలిగి ఉండవు, కానీ ఈ వ్యాసంలో వాటి గురించి కొన్ని మాటలు చెప్పడం సమంజసమని నేను భావిస్తున్నాను. మన దగ్గర లాంబ్డా ఎక్స్‌ప్రెషన్ ఉందని అనుకుందాం, అది ప్రత్యేకంగా ఏమీ చేయదు, కానీ ఒక పద్ధతిని పిలుస్తుంది.

x -> System.out.println(x)
ఇది కొన్ని స్వీకరించింది xమరియు కేవలం కాల్స్ System.out.println(), పాస్ x. ఈ సందర్భంలో, మేము దానిని కావలసిన పద్ధతికి సూచనతో భర్తీ చేయవచ్చు. ఇలా:

System.out::println
అది నిజం — చివరికి కుండలీకరణాలు లేవు! ఇక్కడ మరింత పూర్తి ఉదాహరణ:

List<String> strings = new LinkedList<>(); 

strings.add("Dota"); 
strings.add("GTA5"); 
strings.add("Halo"); 

strings.forEach(x -> System.out.println(x));
చివరి పంక్తిలో, మేము forEach()పద్ధతిని ఉపయోగిస్తాము, ఇది ఇంటర్ఫేస్ను అమలు చేసే వస్తువును తీసుకుంటుంది Consumer. మళ్ళీ, ఇది ఒక ఫంక్షనల్ ఇంటర్ఫేస్, కేవలం ఒక void accept(T t)పద్ధతిని కలిగి ఉంటుంది. దీని ప్రకారం, మేము ఒక పరామితిని కలిగి ఉన్న లాంబ్డా వ్యక్తీకరణను వ్రాస్తాము (ఇది ఇంటర్‌ఫేస్‌లోనే టైప్ చేయబడినందున, మేము పారామితి రకాన్ని పేర్కొనము; మేము దానిని పిలుస్తాము అని మాత్రమే సూచిస్తాము ) x. లాంబ్డా వ్యక్తీకరణ యొక్క శరీరంలో, మేము పద్ధతిని accept()పిలిచినప్పుడు అమలు చేయబడే కోడ్‌ను వ్రాస్తాము. ఇక్కడ మనం వేరియబుల్‌లో ముగిసిన వాటిని ప్రదర్శిస్తాము x. ఇదే forEach()పద్ధతి సేకరణలోని అన్ని అంశాల ద్వారా పునరావృతమవుతుంది మరియు accept()అమలుపై పద్ధతిని పిలుస్తుందిConsumerఇంటర్‌ఫేస్ (మా లాంబ్డా), సేకరణలోని ప్రతి అంశంలో ప్రయాణిస్తుంది. నేను చెప్పినట్లుగా, మేము అటువంటి లాంబ్డా వ్యక్తీకరణను (వేరే పద్ధతిని వర్గీకరించేది) కావలసిన పద్ధతికి సూచనతో భర్తీ చేయవచ్చు. అప్పుడు మా కోడ్ ఇలా కనిపిస్తుంది:

List<String> strings = new LinkedList<>(); 

strings.add("Dota"); 
strings.add("GTA5"); 
strings.add("Halo");

strings.forEach(System.out::println);
ప్రధాన విషయం ఏమిటంటే println()మరియు accept()పద్ధతుల యొక్క పారామితులు సరిపోలడం. లాంబ్డా ఎక్స్‌ప్రెషన్‌లకు బదులుగా ఈ println()పద్ధతి ఏదైనా (ఇది అన్ని ఆదిమ రకాలు మరియు అన్ని వస్తువులకు ఓవర్‌లోడ్ చేయబడింది) అంగీకరించవచ్చు కాబట్టి, మేము పద్ధతికి సూచనను println()పంపవచ్చు forEach(). అప్పుడు forEach()సేకరణలోని ప్రతి మూలకాన్ని తీసుకొని నేరుగా పద్ధతికి పంపుతుంది println(). దీన్ని మొదటిసారిగా ఎదుర్కొన్న ఎవరికైనా, మేము కాల్ చేయడం లేదని దయచేసి గమనించండి System.out.println()(పదాల మధ్య చుక్కలతో మరియు చివర కుండలీకరణాలతో). బదులుగా, మేము ఈ పద్ధతికి సూచనను పంపుతున్నాము. మనం ఇలా వ్రాస్తే

strings.forEach(System.out.println());
మాకు సంకలన లోపం ఉంటుంది. కు కాల్ చేయడానికి ముందు forEach(), జావా అది System.out.println()కాల్ చేయబడిందని చూస్తుంది, కాబట్టి అది రిటర్న్ విలువ అని అర్థం చేసుకుంటుంది మరియు ఆబ్జెక్ట్‌ను ఆశించే దానికి బదులుగా పాస్ voidచేయడానికి ప్రయత్నిస్తుంది . voidforEach()Consumer

పద్ధతి సూచనల కోసం సింటాక్స్

ఇది చాలా సులభం:
  1. మేము ఇలాంటి స్టాటిక్ పద్ధతికి సూచనను పంపుతాము:ClassName::staticMethodName

    
    public class Main { 
    
        public static void main(String[] args) { 
    
            List<String> strings = new LinkedList<>(); 
            strings.add("Dota"); 
            strings.add("GTA5"); 
            strings.add("Halo"); 
    
            strings.forEach(Main::staticMethod); 
        } 
    
        private static void staticMethod(String s) { 
    
            // Do something 
        } 
    }
    
  2. మేము ఇప్పటికే ఉన్న ఆబ్జెక్ట్‌ని ఉపయోగించి నాన్-స్టాటిక్ పద్ధతికి సూచనను పంపుతాము, ఇలా:objectName::instanceMethodName

    
    public class Main { 
    
        public static void main(String[] args) { 
    
            List<String> strings = new LinkedList<>();
            strings.add("Dota"); 
            strings.add("GTA5"); 
            strings.add("Halo"); 
    
            Main instance = new Main(); 
            strings.forEach(instance::nonStaticMethod); 
        } 
    
        private void nonStaticMethod(String s) { 
    
            // Do something 
        } 
    }
    
  3. మేము ఈ క్రింది విధంగా అమలు చేసే తరగతిని ఉపయోగించి నాన్-స్టాటిక్ పద్ధతికి సూచనను పంపుతాము:ClassName::methodName

    
    public class Main { 
    
        public static void main(String[] args) { 
    
            List<User> users = new LinkedList<>(); 
            users.add (new User("John")); 
            users.add(new User("Paul")); 
            users.add(new User("George")); 
    
            users.forEach(User::print); 
        } 
    
        private static class User { 
            private String name; 
    
            private User(String name) { 
                this.name = name; 
            } 
    
            private void print() { 
                System.out.println(name); 
            } 
        } 
    }
    
  4. మేము ఇలాంటి కన్స్ట్రక్టర్‌కు సూచనను పంపుతాము:ClassName::new

    మీరు ఇప్పటికే ఒక కాల్‌బ్యాక్‌గా పని చేసే పద్ధతిని కలిగి ఉన్నప్పుడు పద్ధతి సూచనలు చాలా సౌకర్యవంతంగా ఉంటాయి. ఈ సందర్భంలో, పద్ధతి యొక్క కోడ్‌ను కలిగి ఉన్న లాంబ్డా వ్యక్తీకరణను వ్రాయడానికి లేదా పద్ధతిని పిలిచే లాంబ్డా వ్యక్తీకరణను వ్రాయడానికి బదులుగా, మేము దానికి సూచనను పంపుతాము. అంతే.

అనామక తరగతులు మరియు లాంబ్డా వ్యక్తీకరణల మధ్య ఆసక్తికరమైన వ్యత్యాసం

అనామక తరగతిలో, thisకీవర్డ్ అనామక తరగతి యొక్క వస్తువును సూచిస్తుంది. కానీ మనం దీనిని లాంబ్డా లోపల ఉపయోగిస్తే, మేము కలిగి ఉన్న తరగతి యొక్క వస్తువుకు ప్రాప్యతను పొందుతాము. మేము నిజానికి లాంబ్డా వ్యక్తీకరణను వ్రాసినది. లాంబ్డా వ్యక్తీకరణలు అవి వ్రాసిన తరగతి యొక్క ప్రైవేట్ పద్ధతిలో సంకలనం చేయబడినందున ఇది జరుగుతుంది. నేను ఈ "లక్షణాన్ని" ఉపయోగించమని సిఫార్సు చేయను, ఎందుకంటే ఇది ఒక దుష్ప్రభావం కలిగి ఉంటుంది మరియు ఇది ఫంక్షనల్ ప్రోగ్రామింగ్ సూత్రాలకు విరుద్ధంగా ఉంటుంది. ఈ విధానం OOPకి పూర్తిగా అనుగుణంగా ఉంటుందని పేర్కొంది. ;)

నేను నా సమాచారాన్ని ఎక్కడ పొందాను మరియు మీరు ఇంకా ఏమి చదవాలి?

మరియు, వాస్తవానికి, నేను Googleలో టన్నుల కొద్దీ అంశాలను కనుగొన్నాను :)
వ్యాఖ్యలు
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION