সি # 'এর' ফলন 'কীওয়ার্ডের সমান জাভা আছে কি?


112

আমি জানি জাভাতে সরাসরি কোনও সমতুল্য নেই, তবে সম্ভবত কোনও তৃতীয় পক্ষ?

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


6
আমি জানি আমি জানি. তবে আমি মনে করি আরও ভাষা জানা আরও শক্তি। তদুপরি, আমি এই মুহুর্তে যে সংস্থার জন্য কাজ করি সে ক্ষেত্রে ব্যাকএন্ড ডেভলপমেন্ট (যা আমি করছি) জাভাতে করা হচ্ছে, তাই আমি সত্যিই ভাষাটি চয়ন করতে পারি না :(
রিপার 234

উত্তর:


91

আমি যে দুটি অপশন সম্পর্কে জানি তা হ'ল 2007 এর অ্যাভিয়াড বেন ডভের ইনফোমেন্সার্স-সংগ্রহ গ্রন্থাগার এবং ২০০৮ সালের জিম ব্ল্যাকারের ইয়েলড অ্যাডাপ্টার লাইব্রেরি (যা অন্য উত্তরেও উল্লেখ করা হয়েছে)।

উভয়ই আপনাকে yield returnজাভাতে পছন্দ মতো কনস্ট্রাক্ট সহ কোড লেখার অনুমতি দেবে , তাই উভয়ই আপনার অনুরোধটি পূরণ করবে। দুজনের মধ্যে উল্লেখযোগ্য পার্থক্য হ'ল:

বলবিজ্ঞান

আভিয়াদের লাইব্রেরি বাইকোড ম্যানিপুলেশন ব্যবহার করছে যখন জিম এর মাল্টিথ্রেডিং ব্যবহার করে। আপনার প্রয়োজনের উপর নির্ভর করে প্রত্যেকের নিজস্ব সুবিধা এবং অসুবিধা থাকতে পারে। এটি সম্ভবত আভিয়াডের সমাধানটি দ্রুততর, যখন জিম এর বেশি বহনযোগ্য (উদাহরণস্বরূপ, আমি মনে করি না অ্যাভিডের লাইব্রেরি অ্যান্ড্রয়েডে কাজ করবে)।

ইন্টারফেস

আভিয়াদের লাইব্রেরিতে একটি ক্লিনার ইন্টারফেস রয়েছে - এখানে একটি উদাহরণ রয়েছে:

Iterable<Integer> it = new Yielder<Integer>() {
    @Override protected void yieldNextCore() {
        for (int i = 0; i < 10; i++) {
            yieldReturn(i);
            if (i == 5) yieldBreak();
        }
    }
};

যদিও জিম এর উপায়টি আরও জটিল, আপনার adeptএকটি জেনেরিকের প্রয়োজন Collectorযা একটি collect(ResultHandler)পদ্ধতি আছে ... উঘা। যাইহোক, আপনি জুমের তথ্য দ্বারা জিমের কোডের চারপাশে এই মোড়কের মতো কিছু ব্যবহার করতে পারেন যা এটি ব্যাপকভাবে সরল করে:

Iterable<Integer> it = new Generator<Integer>() {
    @Override protected void run() {
        for (int i = 0; i < 10; i++) {
            yield(i);
            if (i == 5) return;
        }
    }
};

লাইসেন্স

আভিয়াদের সমাধান বিএসডি।

জিমের সমাধানটি পাবলিক ডোমেন এবং উপরে উল্লিখিত এর মোড়কটিও এটি।


3
চমত্কার উত্তর। আপনি কেবল প্রশ্নের পুরোপুরি উত্তরই দেননি, আপনি এটি খুব পরিষ্কার পদ্ধতিতে করেছিলেন। এছাড়াও, আমি আপনার উত্তরের ফর্ম্যাট এবং আপনি কীভাবে লাইসেন্স সম্পর্কিত তথ্য অন্তর্ভুক্ত করেছেন তা পছন্দ করি। দুর্দান্ত উত্তর দিন! :)
ম্যালকম

1
পেয়ারা এর ভুলবেন না AbstractIterator
shmosel

আমি এখানেই আরেকটি (এমআইটি-লাইসেন্সধারী) সমাধান প্রকাশ করেছি, যা নির্মাতার জন্য পৃথক থ্রেড প্রবর্তন করে এবং প্রযোজক এবং গ্রাহকের মধ্যে একটি সীমাবদ্ধ সারি সেট করে: github.com/lukehutch/Producer
লূক হাচিসন

নোটটি yield(i)জেডিকে ১৩ হিসাবে ভাঙ্গবে, যেহেতু yieldনতুন জাভা বিবৃতি / সংরক্ষিত কীওয়ার্ড হিসাবে যুক্ত করা হচ্ছে।
লুক হাচিসন

14

এই দুটি পদ্ধতিরই কিছুটা পরিষ্কার করা যায় এখন জাভাতে লাম্বডাস রয়েছে। আপনি যেমন কিছু করতে পারেন

public Yielderable<Integer> oneToFive() {
    return yield -> {
        for (int i = 1; i < 10; i++) {
            if (i == 6) yield.breaking();
            yield.returning(i);
        }
    };
}

আমি এখানে আরও কিছু ব্যাখ্যা।


4
Yielderable? এটা ঠিক করা উচিত নয় Yieldable? (ক্রিয়া শুধু 'ফলন' হচ্ছে না 'yielder' বা 'yielderate' বা যাই হোক না কেন)
Jochem Kuijpers

yield -> { ... }yieldনতুন জাভা স্টেটমেন্ট / সংরক্ষিত কীওয়ার্ড হিসাবে যুক্ত করা হওয়ায় , জেডিকে ১৩ হিসাবে ব্রেক হবে ।
লুক হাচিসন

1

আমি জানি এটি একটি খুব পুরানো প্রশ্ন, এবং উপরে বর্ণিত দুটি উপায় রয়েছে:

  • বাইটকোড ম্যানিপুলেশন পোর্টিংয়ের সময় এতটা সহজ নয়;
  • থ্রেড-ভিত্তিক yieldযা স্পষ্টতই সম্পদের ব্যয় করে।

তবে yieldজাভাতে জেনারেটর বাস্তবায়নের আরও একটি তৃতীয় এবং সম্ভবত সবচেয়ে প্রাকৃতিক উপায় রয়েছে যা সি # ২.০+ সংকলক yield return/breakপ্রজন্মের জন্য যা করেন তার নিকটতম বাস্তবায়ন : লম্বোক-পিজি । এটি সম্পূর্ণরূপে একটি রাষ্ট্রের মেশিনের উপর ভিত্তি করে এবং javacউত্স কোড এএসটি পরিচালনা করার জন্য কঠোর সহযোগিতা প্রয়োজন । দুর্ভাগ্যক্রমে, লম্বোক-পিজি সমর্থন বন্ধ হয়ে গেছে বলে মনে হচ্ছে (এক বা দুই বছরের বেশি সময় ধরে কোনও রিপোজিটরির ক্রিয়াকলাপ নেই) এবং মূল প্রকল্প লোমবকের দুর্ভাগ্যক্রমে yieldবৈশিষ্ট্যের অভাব রয়েছে (এটিতে ইক্যালিপস, ইন্টেলিজ আইডিইএ সমর্থন যেমন আরও ভাল আইডিই রয়েছে)।


1

স্ট্রিম.আইরেট (বীজ, বীজ অপারেটর) .মিলিট (এন) .পরিচা (ক্রিয়া) ফলন অপারেটরের মতো নয়, তবে আপনার নিজের জেনারেটরগুলি এভাবে লেখার পক্ষে কার্যকর হতে পারে:

import java.util.stream.Stream;
public class Test01 {
    private static void myFoo(int someVar){
        //do some work
        System.out.println(someVar);
    }
    private static void myFoo2(){
        //do some work
        System.out.println("some work");
    }
    public static void main(String[] args) {
        Stream.iterate(1, x -> x + 1).limit(15).forEach(Test01::myFoo);     //var1
        Stream.iterate(1, x -> x + 1).limit(10).forEach(item -> myFoo2());  //var2
    }
}

0

যদি আপনি ইতিমধ্যে কোনও পর্যবেক্ষককে "ইয়েল্ডার" হিসাবে ব্যবহার করতে আপনার প্রকল্পে আরএক্সজাভা ব্যবহার করছেন তবে আমিও পরামর্শ দেব । আপনি যদি নিজের পর্যবেক্ষণযোগ্য করে থাকেন তবে এটি একই ধরণের ফ্যাশনে ব্যবহৃত হতে পারে।

public class Example extends Observable<String> {

    public static void main(String[] args) {
        new Example().blockingSubscribe(System.out::println); // "a", "b", "c", "d"
    }

    @Override
    protected void subscribeActual(Observer<? super String> observer) {
        observer.onNext("a"); // yield
        observer.onNext("b"); // yield
        observer.onNext("c"); // yield
        observer.onNext("d"); // yield
        observer.onComplete(); // finish
    }
}

পর্যবেক্ষণযোগ্যগুলিকে পুনরাবৃত্তিতে রূপান্তর করা যায় যাতে আপনি এগুলি লুপের জন্য আরও বেশি traditionalতিহ্যবাহী ব্যবহার করতে পারেন। এছাড়াও আরএক্সজাভা আপনাকে সত্যিকারের শক্তিশালী সরঞ্জাম দেয়, তবে আপনার যদি কেবল সাধারণ কিছু প্রয়োজন হয় তবে সম্ভবত এটি একটি ওভারকিল হবে।


0

আমি এখানেই অন্য একটি (এমআইটি-লাইসেন্সধারী) সমাধান প্রকাশ করেছি , যা নির্মাতাকে পৃথক থ্রেডে প্রবর্তন করে এবং প্রযোজক এবং গ্রাহকের মধ্যে একটি সীমাবদ্ধ সারি সেট করে, উত্পাদক এবং ভোক্তার মধ্যে সমান্তরাল পাইপলাইনের অনুমতি দেয় (তাই) যেটি ভোক্তা পূর্ববর্তী আইটেমটি উত্পাদন করতে কাজ করতে পারে যখন প্রযোজক পরবর্তী আইটেম উত্পাদন করতে কাজ করছেন)।

আপনি এই বেনামে অভ্যন্তর শ্রেণীর ফর্মটি ব্যবহার করতে পারেন:

Iterable<T> iterable = new Producer<T>(queueSize) {
    @Override
    public void producer() {
        produce(someT);
    }
};

উদাহরণ স্বরূপ:

for (Integer item : new Producer<Integer>(/* queueSize = */ 5) {
    @Override
    public void producer() {
        for (int i = 0; i < 20; i++) {
            System.out.println("Producing " + i);
            produce(i);
        }
        System.out.println("Producer exiting");
    }
}) {
    System.out.println("  Consuming " + item);
    Thread.sleep(200);
}

অথবা আপনি বয়লারপ্লেটটি কাটাতে ল্যাম্বদা স্বরলিপি ব্যবহার করতে পারেন:

for (Integer item : new Producer<Integer>(/* queueSize = */ 5, producer -> {
    for (int i = 0; i < 20; i++) {
        System.out.println("Producing " + i);
        producer.produce(i);
    }
    System.out.println("Producer exiting");
})) {
    System.out.println("  Consuming " + item);
    Thread.sleep(200);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.