java কেন টেকসই<টি> স্ট্রিম() এবং সমান্তরাল স্ট্রিম() পদ্ধতি প্রদান করে না?




jdk download for windows 10 64 bit (3)

এটি একটি ভুল ছিল না; ২013 সালের জুনে ইজি লিস্টে বিস্তারিত আলোচনা ছিল।

বিশেষজ্ঞ গ্রুপের সুনির্দিষ্ট আলোচনা এই থ্রেডে মূলত।

যদিও এটি "সুস্পষ্ট" বলে মনে হয়েছিল (প্রাথমিকভাবে এমনকি বিশেষজ্ঞ গোষ্ঠীর কাছেও) যে stream() Iterable উপর ইন্দ্রিয় বজায় রাখতে পারে বলে ধারণা করা হয়, Iterable এত সাধারণ হয়ে ওঠে, কারণ সুস্পষ্ট স্বাক্ষর:

Stream<T> stream()

আপনি কি করতে চান সবসময় ছিল না। কিছু জিনিস যা Iterable<Integer> পরিবর্তে তাদের স্ট্রিম পদ্ধতিটি একটি IntStream , উদাহরণস্বরূপ। কিন্তু স্ট্রাইক stream() পদ্ধতিটি এই উচ্চতর অনুক্রমের মধ্যে আধিপত্যকে অসম্ভব করে তুলবে। সুতরাং পরিবর্তে, আমরা একটি spliterator() পদ্ধতি সরবরাহ করে, একটি Iterable থেকে একটি Stream তৈরি করা সত্যিই সহজ করে IterableCollection stream() বাস্তবায়ন ঠিক করা হয়:

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

কোনও ক্লায়েন্ট তাদের সাথে যে স্ট্রিমটি চান তা পেতে পারেন:

Stream s = StreamSupport.stream(iter.spliterator(), false);

শেষ পর্যন্ত আমরা সিদ্ধান্ত Iterable যে stream() যোগ করা stream() Iterable stream() ভুল হবে।

আমি আশ্চর্য কেন ইন্টারফেস ইন্টারফেস stream() এবং parallelStream() stream() parallelStream() পদ্ধতিগুলি সরবরাহ করে না। নিচের ক্লাসটি বিবেচনা করুন:

public class Hand implements Iterable<Card> {
    private final List<Card> list = new ArrayList<>();
    private final int capacity;

    //...

    @Override
    public Iterator<Card> iterator() {
        return list.iterator();
    }
}

ট্রেডিং কার্ড গেমটি খেলার সময় এটি আপনার হাতের হাতে কার্ড থাকতে পারে।

মূলত এটি একটি List<Card> wraps, সর্বোচ্চ ক্ষমতা নিশ্চিত করে এবং কিছু অন্যান্য দরকারী বৈশিষ্ট্য উপলব্ধ করা হয়। এটি একটি List<Card> হিসাবে সরাসরি বাস্তবায়ন হিসাবে ভাল।

এখন, দৃঢ়তার জন্য আমি ভাবলাম Iterable<Card> প্রয়োগ করা ভালো হবে, যেমন আপনি যদি এটিতে লুপ করতে চান তবে বর্ধিত for-loops ব্যবহার করতে পারেন। (আমার Hand Iterable<Card> একটি get(int index) পদ্ধতি সরবরাহ করে, তাই Iterable<Card> আমার মতামত অনুসারে ন্যায্য।)

Iterable ইন্টারফেসটি নিম্নোক্ত (জাভাডাক থেকে বামে) প্রদান করে:

public interface Iterable<T> {
    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

এখন আপনি একটি স্ট্রিম পেতে পারেন:

Stream<Hand> stream = StreamSupport.stream(hand.spliterator(), false);

তাই আসল প্রশ্ন সম্মুখের দিকে:

  • কেন stream() এবং parallelStream() stream() কে Iterable<T> একটি ডিফল্ট পদ্ধতি সরবরাহ করা সম্ভব Iterable<T> , আমি এমন অসম্ভব বা অবাঞ্ছিত কিছু দেখতে পাব না?

আমি সম্পর্কিত একটি সম্পর্কিত প্রশ্ন নিম্নলিখিত যদিও: কেন স্ট্রিম <টি> ইটারেবল বাস্তবায়িত না <টি>?
যা অদ্ভুত যথেষ্ট এটি কিছুটা অন্য উপায় প্রায় এটি করার সুপারিশ।


Answer #1

আমি Lambda মেইলিং তালিকা প্রকল্পের বেশ কয়েকটি তদন্ত করেছি এবং আমি মনে করি আমি কিছু আকর্ষণীয় আলোচনা খুঁজে পেয়েছি।

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

ল্যাম্বা লিবি স্পেক বিশেষজ্ঞরা

আমি ল্যাম্বা লিব স্পেক বিশেষজ্ঞদের মেইলিং লিস্টে এই বিষয়ে একটি আলোচনা খুঁজে পেয়েছি:

Iterable/Iterator.stream() অধীনে স্যাম পুলাররা বলেছিলেন:

আমি ব্রায়ানকে কিভাবে সীমিত / সাবস্ট্রিম কার্যকারিতা [1] প্রয়োগ করা হতে পারে তা দেখানোর সাথে কাজ করছিলাম এবং তিনি ইটারেটারে রূপান্তর প্রস্তাব করার পক্ষে সঠিক উপায় ছিল। আমি যে সমাধান সম্পর্কে চিন্তা ছিল কিন্তু একটি ইটারেটার গ্রহণ এবং একটি প্রবাহে এটি চালু করার কোন সুস্পষ্ট উপায় খুঁজে পাইনি। এটি সক্রিয় হয়েছে, এটি আপনাকে প্রথমে বিভাজককে বিভাজক রূপে রূপান্তর করতে হবে এবং তারপরে বিভাজককে একটি প্রবাহে রূপান্তর করতে হবে। সুতরাং এই আমাকে পুনর্বিবেচনার জন্য আনা উচিত কিনা আমাদের ইন্টেলেবল / ইটারেটারের সরাসরি বন্ধ থাকা উচিত।

আমার পরামর্শটি অন্তত ইটারেটারে থাকা উচিত যাতে আপনি দুটো জনের মধ্যে পরিষ্কারভাবে চলতে পারেন এবং এটি করার পরিবর্তে এটি সহজেই আবিষ্কারযোগ্য হতে পারে:

Streams.stream (Spliterators.spliterator অজ্ঞাতসাধন (ইটারারেটর, Spliterator.ORDERED))

এবং তারপর ব্রায়ান গোয়েজ প্রতিক্রিয়া জানিয়েছেন :

আমি মনে করি স্যামের বক্তব্য ছিল যে লাইব্রেরির ক্লাসগুলি আপনাকে প্রচুর পরিমাণে দেয় তবে আপনাকে অবশ্যই নিজের spl splitter লিখতে দেয় না। তাই আপনি করতে পারেন কল স্ট্রিম (spliterator অজ্ঞাতসম্পন্ন (ইটারারেটর))। স্যাম প্রস্তাব করছে যে আমরা আপনার জন্য এটি করার জন্য Iterator.stream () সংজ্ঞায়িত করি।

আমি লাইব্রেরি লেখক / উন্নত ব্যবহারকারীদের জন্য প্রবাহ () এবং বিভক্তকারী () পদ্ধতিগুলিকে রাখতে চাই।

এবং পরে

"একটি স্প্লিটারেটর লেখা একটি ইটারেটর লেখার চেয়ে আরও সহজ, আমি একটি ইটারেটরের পরিবর্তে একটি স্প্লিটারেটর লিখতে পছন্দ করি (নির্বাচক তাই 90s :) :)"

আপনি পয়েন্ট অনুপস্থিত, যদিও। ইতিমধ্যে আপনি একটি Iterator হাত আছে যে সেখানে আউট zillions আছে। এবং তাদের অনেকে বিভক্তকারী-প্রস্তুত নয়।

Lambda মেইলিং তালিকা পূর্ববর্তী আলোচনা

এটি আপনি উত্তর খুঁজছেন না হতে পারে কিন্তু প্রকল্প Lambda মেইলিং তালিকাতে এই সংক্ষিপ্ত আলোচনা করা হয়েছিল। সম্ভবত এই বিষয় উপর একটি বিস্তৃত আলোচনা উত্সাহিত করতে সাহায্য করে।

Iterable থেকে স্ট্রিমস অধীনে ব্রায়ান Goetz এর শব্দের মধ্যে:

পিছপা...

একটি স্ট্রিম তৈরি করার অনেক উপায় আছে। উপাদানগুলি কীভাবে বর্ণনা করতে হবে তার সম্পর্কে আপনার কাছে আরো তথ্য, স্ট্রিম লাইব্রেরির আরও কার্যকারিতা এবং কর্মক্ষমতা আপনাকে দিতে পারে। সর্বাধিক তথ্য অন্তত, তারা হয়:

iterator

Iterator + আকার

Spliterator

Spliterator যে তার আকার জানে

Splitator যে তার আকার জানেন, এবং আরও জানেন যে সব উপ-বিভক্ত তাদের আকার জানেন।

(কিছু কিছু ক্ষেত্রে অবাক হওয়ার কিছু আছে যে আমরা প্রশ্নগুলি (উপাদান প্রতি কাজ) ননট্রিয়িয়াল ক্ষেত্রে যেখানে একটি বোকা ইটারারেটর থেকে সমান্তরাল বের করতে পারি।)

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

স্টিফেনের দ্বারা এখানে বর্ণিত API অনুশীলনের একটি উপসর্গ, সংগ্রহের বদলে ইটারেবল গ্রহণ করার জন্য, আপনি "ছোট পাইপ" এর মাধ্যমে জিনিসগুলি জোরদার করছেন এবং এটি কার্যকর হতে পারে এমন কারণে আকারের তথ্য বাতিল করা। এটি ঠিক আছে যদি আপনি যা করতে যাচ্ছেন তা সবই এটির জন্য, তবে যদি আপনি আরো বেশি কিছু করতে চান তবে এটি আরও ভাল হবে যদি আপনি আপনার সমস্ত তথ্য সংরক্ষণ করতে পারেন।

ইটারেবল দ্বারা সরবরাহিত ডিফল্টটি আসলেই একটি বেদনাদায়ক হবে - যদিও আইটারেবলের বিশাল সংখ্যক তথ্য সেই তথ্যটি জানবে তবে এটি আকার বাতিল করবে।

দ্বন্দ্ব?

যদিও এটি দেখে মনে হচ্ছে যে বিশেষজ্ঞরা গ্রুপের স্ট্রিমগুলির প্রাথমিক নকশা যা প্রাথমিকভাবে এটিরেটরগুলির উপর ভিত্তি করে তৈরি হয়েছে তার উপর ভিত্তি করে আলোচনাটি করে।

এমনকী, এটি লক্ষ্য করা আকর্ষণীয় যে সংগ্রহের মতো ইন্টারফেসে স্ট্রিম পদ্ধতিটি নিম্নরূপ সংজ্ঞায়িত করা হয়েছে:

default Stream<E> stream() {
   return StreamSupport.stream(spliterator(), false);
}

ইটারেবল ইন্টারফেসে একই কোড ব্যবহার করা যেতে পারে যা সঠিক হতে পারে।

তাই, আমি এই প্রশ্নের উত্তর সম্ভবত সন্তোষজনক নয়, তবে আলোচনার জন্য এখনও আকর্ষণীয়।

প্রত্যয়ন প্রমাণ

মেইলিং লিস্টে বিশ্লেষণ চালিয়ে যাওয়া, দেখে মনে হচ্ছে splitIterator পদ্ধতিটি মূলত সংগ্রহস্থলের ইন্টারফেসে ছিল এবং ২013 সালে কিছু সময়ে তারা ইটারেবলে স্থানান্তরিত হয়েছিল।

Iterable সংগ্রহ থেকে SplitIterator টানুন

উপসংহার / তত্ত্ব?

তারপরে সম্ভাবনা আছে যে ইটারেবল পদ্ধতির অভাব কেবল একটি ভুল, কারণ দেখে মনে হচ্ছে তারা স্ট্রীম পদ্ধতিটিও সরানো উচিত ছিল যখন তারা SplitIterator কে সংগ্রহস্থল থেকে ইটারেবল থেকে সরিয়ে নিয়েছিল।

অন্যান্য কারণ আছে যে স্পষ্ট না হয়। অন্য কেউ অন্য তত্ত্ব আছে?


Answer #2

যদি আপনি আকারটি জানেন তবে আপনি java.util.Collection ব্যবহার করতে পারেন যা stream() পদ্ধতি সরবরাহ করে:

public class Hand extends AbstractCollection<Card> {
   private final List<Card> list = new ArrayList<>();
   private final int capacity;

   //...

   @Override
   public Iterator<Card> iterator() {
       return list.iterator();
   }

   @Override
   public int size() {
      return list.size();
   }
}

এবং তারপর:

new Hand().stream().map(...)

আমি একই সমস্যার মুখোমুখি হয়েছিলাম এবং অবাক হয়েছি যে আমার Iterable বাস্তবায়ন খুব সহজে size() পদ্ধতিটি যোগ করে একটি Iterable বাস্তবায়নে প্রসারিত করা যেতে পারে (সৌভাগ্যক্রমে আমার সংগ্রহের আকার ছিল :-)

আপনি Spliterator<E> spliterator() বিবেচনা করতে হবে।





java-8