"স্ট্রিম ইতিমধ্যে চালু বা বন্ধ হয়ে গেছে" এড়ানোর জন্য একটি স্ট্রিম অনুলিপি করুন


121

আমি একটি জাভা 8 স্ট্রিমটির নকল করতে চাই যাতে আমি এর সাথে দুবার ডিল করতে পারি। আমি collectএকটি তালিকা হিসাবে এবং এটি থেকে নতুন স্ট্রিমগুলি পেতে পারি;

// doSomething() returns a stream
List<A> thing = doSomething().collect(toList());
thing.stream()... // do stuff
thing.stream()... // do other stuff

তবে আমি মনে করি আরও দক্ষ / মার্জিত উপায় থাকা উচিত।

স্ট্রিমটিকে কোনও সংগ্রহে পরিণত না করে কপি করার কোনও উপায় আছে?

আমি আসলে একটি স্ট্রিমের সাথে কাজ করছি Either, সুতরাং ডান প্রজেকশনটিতে যাওয়ার আগে এবং অন্য কোনও উপায়ে व्यवहार করার আগে বাম প্রক্ষেপণকে একপথে প্রক্রিয়া করতে চাই। এই জাতীয় ধরনের (যা এখনও পর্যন্ত আমি এর toListসাথে কৌশলটি ব্যবহার করতে বাধ্য হই )।

List<Either<Pair<A, Throwable>, A>> results = doSomething().collect(toList());

Stream<Pair<A, Throwable>> failures = results.stream().flatMap(either -> either.left());
failures.forEach(failure -> ... );

Stream<A> successes = results.stream().flatMap(either -> either.right());
successes.forEach(success -> ... );

আপনি কি "একতরফা প্রক্রিয়াজাতকরণ" আরও বিস্তারিতভাবে বর্ণনা করতে পারেন ... আপনি কি বস্তুগুলি গ্রাস করছেন? তাদের ম্যাপিং? পার্টিশনবাই () এবং গ্রুপিংবিয়ের মাধ্যমে () আপনাকে সরাসরি 2+ তালিকায় নিয়ে যেতে পারে, তবে আপনি প্রথমে ম্যাপিং করে বা আপনার ফর (প্রতিটি) () জন্য সিদ্ধান্তের কাঁটাচামচ রেখে উপকৃত হতে পারেন।
অজাহানচার্লস

কিছু ক্ষেত্রে, যদি আমরা অসীম স্ট্রিমের সাথে কাজ করে থাকি তবে এটি সংগ্রহে রূপান্তর করা কোনও বিকল্প হতে পারে না। আপনি এখানে স্মৃতিচারণের
মিগুয়েল গ্যাম্বোয়ায়

উত্তর:


88

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

আপনি যদি একই ডেটা পুনরায় ব্যবহার করতে চান তবে সংজ্ঞা অনুসারে আপনাকে হয় এটিকে দু'বার তৈরি করতে হবে (নির্ধারিতভাবে) বা এটি সংরক্ষণ করতে হবে। যদি এটি ইতিমধ্যে কোনও সংগ্রহে থাকে তবে দুর্দান্ত; তারপরে এটিকে পুনরাবৃত্তি করা সস্তা।

আমরা "কাঁটাচলা স্ট্রিম" দিয়ে ডিজাইনে পরীক্ষা-নিরীক্ষা করেছি। আমরা যেটি পেয়েছি তা হ'ল এটির সমর্থন করার আসল ব্যয় হয়েছিল; এটি অস্বাভাবিক ক্ষেত্রে ব্যয় করে সাধারণ ক্ষেত্রে (একবার ব্যবহার করুন) বোঝা করে। বড় সমস্যাটি হ'ল "যখন দুটি পাইপলাইন একই হারে ডেটা গ্রহণ না করে তখন কী হয়।" এখন আপনি যেভাবেই হোক বাফারিংয়ে ফিরে এসেছেন। এটি এমন বৈশিষ্ট্য যা স্পষ্টভাবে তার ওজন বহন করে না।

আপনি যদি একই ডেটা বারবার পরিচালনা করতে চান তবে তা সঞ্চয় করুন, বা আপনার ক্রিয়াকলাপটিকে গ্রাহক হিসাবে কাঠামো করুন এবং নিম্নলিখিতগুলি করুন:

stream()...stuff....forEach(e -> { consumerA(e); consumerB(e); });

আপনি আরএক্সজাভা গ্রন্থাগারটিও দেখে নিতে পারেন, কারণ এর প্রসেসিং মডেল নিজেকে এই জাতীয় "স্ট্রিম ফোর্কিং" এর চেয়ে ভাল ধার দেয়।


1
সম্ভবত আমার "দক্ষতা" ব্যবহার করা উচিত ছিল না, আমি স্ট্রিমের সাথে কেন বিরক্ত করব (আমি কোনও কিছু সঞ্চয় না করি) আমি যদি একা হয়ে থাকি তবে যদি আমি যা কিছু করি তা অবিলম্বে তথ্য সংরক্ষণ করে ( toList) কেসটি প্রক্রিয়া করতে সক্ষম হয় ( Eitherকেস উদাহরণ হচ্ছে)?
টবি

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

1
কিন্তু একটি স্ট্রিম পুনরায় ব্যবহার করতে অক্ষমতার কারণে এমন পরিস্থিতি তৈরি হয় যেখানে বিকাশকারী দুটি ভিন্ন উপায়ে স্ট্রিমটি প্রক্রিয়াকরণের জন্য মধ্যবর্তী ফলাফল (সংগ্রহ) সঞ্চয় করতে বাধ্য হয়। এই প্রবণতাটি যে স্ট্রিমটি একাধিকবার উত্পন্ন হয়েছে (আপনি এটি সংগ্রহ না করলেই) পরিষ্কার মনে হয় - কারণ অন্যথায় আপনার সংগ্রহের পদ্ধতির প্রয়োজন হবে না।
নিয়াল Connaughton

@ নিলালকনফটন আমি নিশ্চিত যে আপনার বক্তব্যটি চান তা নিশ্চিত নই। আপনি যদি এটিকে দু'বার অতিক্রম করতে চান তবে কাউকে এটি সঞ্চয় করতে হবে, অথবা আপনাকে এটি পুনরায় জজ করতে হবে। আপনি কি পরামর্শ দিচ্ছেন যে লাইব্রেরিটি যদি কেবল দু'বার প্রয়োজন হয় তবে এটি বাফার করা উচিত? যে নির্বোধ হবে।
ব্রায়ান গয়েটজ

লাইব্রেরিটি এটি বাফার করার পরামর্শ দিচ্ছে না, তবে বলছে যে ওয়ান অফস হিসাবে স্ট্রিম রাখার ফলে এটি এমন লোকদেরকে বীজ প্রবাহকে পুনরায় ব্যবহার করতে বাধ্য করে (যেমন: এটি সংজ্ঞায়িত করার জন্য ঘোষিত যুক্তি ভাগ করে নেওয়া) একত্রিত করতে একাধিক উত্পন্ন স্ট্রিম তৈরি করতে বীজ প্রবাহ, বা এমন কোনও সরবরাহকারী কারখানায় অ্যাক্সেস রয়েছে যা বীজ প্রবাহের সদৃশ তৈরি করবে। উভয় বিকল্পের তাদের ব্যথা পয়েন্ট রয়েছে। এই উত্তরের বিষয়টিতে আরও বিস্তারিত রয়েছে: stackoverflow.com/a/28513908/114200
নিলাল কানফটন

73

Supplierস্ট্রিম পাইপলাইনের সাধারণ অংশগুলি সেট আপ করতে আপনি একটি স্থানীয় ভেরিয়েবল ব্যবহার করতে পারেন ।

থেকে Http://winterbe.com/posts/2014/07/31/java8-stream-tutorial- / :

স্ট্রিম পুনরায় ব্যবহার করা হচ্ছে

জাভা 8 স্ট্রিমগুলি পুনরায় ব্যবহার করা যাবে না। আপনি যেকোনও টার্মিনাল অপারেশন কল করার সাথে সাথে স্ট্রিমটি বন্ধ হয়ে যাবে:

Stream<String> stream = Stream.of("d2", "a2", "b1", "b3", "c")
    .filter(s -> s.startsWith("a"));
stream.anyMatch(s -> true);    // ok
stream.noneMatch(s -> true);   // exception

Calling `noneMatch` after `anyMatch` on the same stream results in the following exception:
java.lang.IllegalStateException: stream has already been operated upon or closed
at 
java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
at 
java.util.stream.ReferencePipeline.noneMatch(ReferencePipeline.java:459)
at com.winterbe.java8.Streams5.test7(Streams5.java:38)
at com.winterbe.java8.Streams5.main(Streams5.java:28)

এই সীমাবদ্ধতা কাটিয়ে উঠতে আমাদের প্রতিটি টার্মিনাল ক্রিয়াকলাপের জন্য একটি নতুন স্ট্রিম চেইন তৈরি করতে হবে যা আমরা কার্যকর করতে চাই, যেমন ইতিমধ্যে সেট করা সমস্ত অন্তর্বর্তী ক্রিয়াকলাপ সহ একটি নতুন স্ট্রিম নির্মাণের জন্য আমরা একটি স্ট্রিম সরবরাহকারী তৈরি করতে পারি:

Supplier<Stream<String>> streamSupplier =
    () -> Stream.of("d2", "a2", "b1", "b3", "c")
            .filter(s -> s.startsWith("a"));

streamSupplier.get().anyMatch(s -> true);   // ok
streamSupplier.get().noneMatch(s -> true);  // ok

প্রতিটি কল get()একটি নতুন স্ট্রিম তৈরি করে যার উপর আমরা কাঙ্ক্ষিত টার্মিনাল অপারেশনটি কল করতে সংরক্ষণ করি are


2
সুন্দর এবং মার্জিত সমাধান। সর্বাধিক উত্সাহিত সমাধানের চেয়ে অনেক বেশি জাভা 8-ইশ।
ডিলানিয়েটো

Supplierযদি এটি Stream"ব্যয়বহুল" পদ্ধতিতে নির্মিত হয় তবে কেবলমাত্র একটি নোট , আপনি প্রতিটি কলের জন্য সেই মূল্যটি প্রদান করবেনSupplier.get() । উদাহরণস্বরূপ, যদি কোনও ডাটাবেস ক্যোয়ারী ... সেই ক্যোয়ারী প্রতিটি সময় সম্পন্ন হয়
জুলিয়েন

আপনি কোনও স্ট্রিম ব্যবহার করেও মানচিত্রের পরে এই ধরণটি অনুসরণ করবেন বলে মনে হয় না। আমি দেখতে পেলাম যে আমাকে এটি Set<Integer>ব্যবহার করে আবার রূপান্তর করতে হয়েছিল collect(Collectors.toSet())... এবং এর উপর বেশ কয়েকটি অপারেশন করতে হবে। আমি চেয়েছিলাম max()এবং যদি একটি নির্দিষ্ট মান দুটি অপারেশন হিসাবে সেট করা থাকে ...filter(d -> d == -1).count() == 1;
জেজিএফএমকে

16

Supplierপ্রতিটি সমাপ্তির ক্রিয়াকলাপের জন্য স্ট্রিম উত্পাদন করতে একটি ব্যবহার করুন ।

Supplier<Stream<Integer>> streamSupplier = () -> list.stream();

যখনই আপনার এই সংগ্রহের একটি স্ট্রিমের প্রয়োজন streamSupplier.get()হবে, একটি নতুন স্ট্রিম পেতে ব্যবহার করুন ।

উদাহরণ:

  1. streamSupplier.get().anyMatch(predicate);
  2. streamSupplier.get().allMatch(predicate2);

আপনি এখানে প্রথম সরবরাহকারী সরবরাহকারী হিসাবে প্রথম হিসাবে আপনাকে উত্সাহিত করুন।
এনজোবিএনএল

9

আমরা একটি প্রয়োগ করেছি duplicate()মধ্যে স্ট্রিম জন্য পদ্ধতি jOOλ নামে একটি মুক্ত উৎস গ্রন্থাগার যে আমরা জন্য ইন্টিগ্রেশন পরীক্ষার উন্নত করার জন্য তৈরি করা jOOQ । মূলত, আপনি কেবল লিখতে পারেন:

Tuple2<Seq<A>, Seq<A>> duplicates = Seq.seq(doSomething()).duplicate();

অভ্যন্তরীণভাবে, একটি বাফার সমস্ত মান সংরক্ষণ করে যা এক স্ট্রিম থেকে গ্রহন করা হয়েছে তবে অন্যটি থেকে নয়। আপনার দুটি স্ট্রিম একই হারে গ্রাস করা হলে এবং থ্রেড-সুরক্ষার অভাবে যদি বেঁচে থাকতে পারেন তবে এটি সম্ভবত তত দক্ষ

অ্যালগরিদম কীভাবে কাজ করে তা এখানে:

static <T> Tuple2<Seq<T>, Seq<T>> duplicate(Stream<T> stream) {
    final List<T> gap = new LinkedList<>();
    final Iterator<T> it = stream.iterator();

    @SuppressWarnings("unchecked")
    final Iterator<T>[] ahead = new Iterator[] { null };

    class Duplicate implements Iterator<T> {
        @Override
        public boolean hasNext() {
            if (ahead[0] == null || ahead[0] == this)
                return it.hasNext();

            return !gap.isEmpty();
        }

        @Override
        public T next() {
            if (ahead[0] == null)
                ahead[0] = this;

            if (ahead[0] == this) {
                T value = it.next();
                gap.offer(value);
                return value;
            }

            return gap.poll();
        }
    }

    return tuple(seq(new Duplicate()), seq(new Duplicate()));
}

আরও উত্স কোড এখানে

Tuple2সম্ভবত আপনার মত হল Pair, টাইপ যেহেতু Seqহয় Streamকিছু উন্নত বৈশিষ্ট্য সঙ্গে।


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

@ তাগিরওয়ালিভ: আপনি থ্রেড-সুরক্ষা সম্পর্কে ঠিক বলেছেন, ভাল বিষয়। সংগ্রহকারীদের সম্মিলনের সাথে এটি কীভাবে করা যায়?
লুকাস এদার

1
আমি বোঝাতে চাইছি যদি কেউ একই স্ট্রিমটি এর মতো দু'বার ব্যবহার করতে চায় তবে Tuple2<Seq<A>>, Seq<A>> t = duplicate(stream); long count = t.collect(counting()); List<A> list = t.collect(toList());তা আরও ভাল Tuple2<Long, List<A>> t = stream.collect(Tuple.collectors(counting(), toList()));। একটি ব্যবহার করে Collectors.mapping/reducingসংগ্রাহক হিসাবে বিভিন্ন স্ট্রিম ক্রিয়াকলাপ প্রকাশ করতে পারে এবং একক ফলে তৈরি টিপল তৈরি করতে বিভিন্ন উপাদান প্রক্রিয়াজাতকরণ করতে পারে। সুতরাং সাধারণভাবে আপনি একবারে নকল ছাড়াই স্ট্রিম গ্রাস করে অনেক কিছু করতে পারেন এবং এটি সমান্তরাল-বান্ধব হবে।
তাগীর ভালিভ

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

1
@ মাআর্টিনাস: ধন্যবাদ, ভাল পয়েন্টার। আমি মাপদণ্ডের জন্য একটি সমস্যা তৈরি করেছি । আমি এটি offer()/ poll()এপিআইয়ের জন্য ব্যবহার করেছি , তবে একটি ArrayDequeসম্ভবত একই কাজ করতে পারে।
লুকাশ এদার

7

আপনি রান্নেবলগুলির একটি স্ট্রিম তৈরি করতে পারেন (উদাহরণস্বরূপ):

results.stream()
    .flatMap(either -> Stream.<Runnable> of(
            () -> failure(either.left()),
            () -> success(either.right())))
    .forEach(Runnable::run);

কোথায় failureএবং successপ্রয়োগ করার জন্য অপারেশনগুলি রয়েছে। তবে এটি বেশ কয়েকটি অস্থায়ী অবজেক্ট তৈরি করবে এবং সংগ্রহ থেকে শুরু করে স্ট্রিমিং / এটিকে দু'বার পুনরুক্ত করার চেয়ে বেশি কার্যকর নাও হতে পারে।


4

একাধিকবার উপাদানগুলি হ্যান্ডেল করার আরেকটি উপায় হ'ল স্ট্রিম.পিয়েক (গ্রাহক) ব্যবহার করা :

doSomething().stream()
.peek(either -> handleFailure(either.left()))
.foreach(either -> handleSuccess(either.right()));

peek(Consumer) প্রয়োজন হিসাবে অনেকবার শৃঙ্খলাবদ্ধ হতে পারে।

doSomething().stream()
.peek(element -> handleFoo(element.foo()))
.peek(element -> handleBar(element.bar()))
.peek(element -> handleBaz(element.baz()))
.foreach(element-> handleQux(element.qux()));

দেখে মনে হচ্ছে এটির জন্য
পিক

2
@ হেক্টরজে অন্য থ্রেডটি উপাদান পরিবর্তন করার বিষয়ে। আমি ধরে নিয়েছি যে এখানে করা হয়নি।
মার্টিন

2

সাইক্লোপস-রিএ্যাক্ট , একটি লাইব্রেরি আমি অবদান রাখছি, এর একটি স্থিতিশীল পদ্ধতি রয়েছে যা আপনাকে একটি স্ট্রিমের নকল করতে দেয় (এবং একটি JOO St স্ট্রিপের টুপল ফেরত দেয়)।

    Stream<Integer> stream = Stream.of(1,2,3);
    Tuple2<Stream<Integer>,Stream<Integer>> streams =  StreamUtils.duplicate(stream);

মন্তব্যগুলি দেখুন, সেখানে কোনও পারফরম্যান্স পেনাল্টি রয়েছে যা কোনও বিদ্যমান স্ট্রিমটিতে নকল ব্যবহার করার সময় ব্যয় করা হবে। আরও কার্যকর পারফরম্যান্ট বিকল্প হ'ল স্ট্রেমেবল ব্যবহার করা: -

এখানে একটি (অলস) স্ট্রেমেবল বর্গও রয়েছে যা একটি স্ট্রিম, অবহেলিত বা অ্যারে থেকে নির্মিত হতে পারে এবং একাধিকবার পুনরায় খেলানো যায়।

    Streamable<Integer> streamable = Streamable.of(1,2,3);
    streamable.stream().forEach(System.out::println);
    streamable.stream().forEach(System.out::println);

AsStreamable.synchronizedFromStream (স্ট্রিম) - এমন স্ট্রিমেবল তৈরি করতে ব্যবহার করা যেতে পারে যা অলসভাবে এটির সমর্থনকারী সংগ্রহকে জনপ্রিয় করে তুলবে, এমনভাবে যাতে থ্রেড জুড়ে ভাগ করা যায়। স্ট্র্যামেবল.ফ্রোম স্ট্রিম (স্ট্রিম) কোনও সিঙ্ক্রোনাইজেশন ওভারহেড ব্যয় করবে না।


2
এবং অবশ্যই এটি লক্ষ করা উচিত যে ফলস্বরূপ স্ট্রিমগুলির উল্লেখযোগ্য সিপিইউ / মেমরি ওভারহেড এবং খুব দুর্বল সমান্তরাল কর্মক্ষমতা রয়েছে। এছাড়াও এই সমাধানটি থ্রেড-নিরাপদ নয় (আপনি ফলস্বরূপ একটি স্ট্রিমটিকে অন্য থ্রেডে পাস করতে পারবেন না এবং সমান্তরালে নিরাপদে এটি প্রক্রিয়া করতে পারবেন না)। এটি অনেক বেশি পারফরম্যান্ট এবং নিরাপদ হবে List<Integer> list = stream.collect(Collectors.toList()); streams = new Tuple2<>(list.stream(), list.stream())(যেমন ওপি পরামর্শ দেয়)। আপনি দয়া করে সাইক্লোপ-স্ট্রিমের লেখক যে উত্তরে তা স্পষ্টভাবে প্রকাশ করুন। পড়ুন এই
তাগীর ভালিভ

আমি লেখক প্রতিফলিত আপডেট। প্রত্যেকের পারফরম্যান্সের বৈশিষ্ট্যগুলি আলোচনা করার জন্য একটি ভাল পয়েন্ট। উপরে আপনার মূল্যায়ন স্ট্রিম ইউটিস.ডুপ্লেকেটের জন্য বেশ স্পট করে। একটি স্ট্রিম থেকে অন্য স্ট্রিমে ডেটা বাফার করে স্ট্রিমটুইলস ডুপ্লিকেট কাজ করে, এতে একটি সিপিইউ এবং মেমরি ওভারহেড উভয়ই থাকে (কেস নির্ভর করে ব্যবহার করুন)। স্ট্র্যামেবল.ওফের জন্য (1,2,3) তবে প্রতিটি সময় সরাসরি অ্যারে থেকে একটি নতুন স্ট্রিম তৈরি করা হয় এবং সমান্তরাল পারফরম্যান্স অন্তর্ভুক্ত পারফরম্যান্সের বৈশিষ্ট্যগুলি সাধারণভাবে তৈরি স্ট্রিমের মতোই হবে।
জন ম্যাকক্লেইন

এছাড়াও, একটি স্ট্রিমেবল ক্লাস রয়েছে যা স্ট্রিম থেকে স্ট্র্যামেবল উদাহরণ তৈরি করতে দেয় তবে স্ট্র্যামেবলকে তৈরি হওয়ার সাথে সাথে এটি সংগ্রহের অ্যাক্সেসকে সিঙ্ক্রোনাইজ করে (AsStreamable.synchronizedFromStream)। এটিকে থ্রেড জুড়ে ব্যবহারের জন্য আরও উপযুক্ত করে তোলা (যদি আপনার এটির প্রয়োজন হয় তবে - আমি একই ধরণের স্ট্রিমগুলি তৈরি এবং পুনরায় ব্যবহারের সময়কালের 99% কল্পনা করব)।
জন ম্যাকক্লেইন

হাই তাগীর - আপনি কি আপনার প্রতিবেদনে প্রকাশ করবেন না যে আপনি একটি প্রতিযোগিতামূলক লাইব্রেরির লেখক?
জন ম্যাকক্লেইন

1
মন্তব্যগুলি উত্তর নয় এবং আমি এখানে আমার লাইব্রেরির বিজ্ঞাপন দিচ্ছি না কারণ আমার লাইব্রেরির স্ট্রিমটিকে নকল করার কোনও বৈশিষ্ট্য নেই (কেবল কারণ আমি মনে করি এটি অকেজো), তাই আমরা এখানে প্রতিযোগিতা করি না। অবশ্যই আমি যখন আমার লাইব্রেরি সম্পর্কিত কোনও সমাধান প্রস্তাব করি তখন আমি সর্বদা স্পষ্টভাবে বলে থাকি যে আমি লেখক।
তাগীর ভালিভ

0

এই বিশেষ সমস্যার জন্য আপনি পার্টিশনও ব্যবহার করতে পারেন। কিছুটা এইরকম

     // Partition Eighters into left and right
     List<Either<Pair<A, Throwable>, A>> results = doSomething();
     Map<Boolean, Object> passingFailing = results.collect(Collectors.partitioningBy(s -> s.isLeft()));
     passingFailing.get(true) <- here will be all passing (left values)
     passingFailing.get(false) <- here will be all failing (right values)

0

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

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.Builder.html

ব্যবহারের ক্ষেত্রে

ধরা যাক আমাদের কর্মচারী স্ট্রিম রয়েছে এবং আমাদের এই স্ট্রিমটি এক্সেল ফাইলে কর্মচারী ডেটা লিখতে এবং তারপরে কর্মচারী সংগ্রহ / টেবিল আপডেট করতে হবে [এটি স্ট্রিম বিল্ডারের ব্যবহার দেখানোর জন্য কেবল ব্যবহারের ক্ষেত্রে]:

Stream.Builder<Employee> builder = Stream.builder();

employee.forEach( emp -> {
   //store employee data to excel file 
   // and use the same object to build the stream.
   builder.add(emp);
});

//Now this stream can be used to update the employee collection
Stream<Employee> newStream = builder.build();

0

আমার একইরকম সমস্যা ছিল এবং আমি তিনটি পৃথক মধ্যবর্তী কাঠামো নিয়ে ভাবতে পারি যেখান থেকে প্রবাহের অনুলিপি তৈরি করতে হবে: ক List, একটি অ্যারে এবং এ Stream.Builder। আমি একটি সামান্য বেঞ্চমার্ক প্রোগ্রাম লিখেছি, যা বলেছিল যে পারফরম্যান্সের দৃষ্টিকোণ থেকে Listঅন্য দুটি তুলনায় প্রায় 30% ধীর ছিল যা মোটামুটি একই রকম ছিল।

অ্যারেতে রূপান্তরিত করার একমাত্র ত্রুটিটি হ'ল যদি আপনার উপাদান টাইপটি একটি জেনেরিক প্রকার হয় (যা আমার ক্ষেত্রে এটি ছিল) তবে এটি জটিল; অতএব আমি একটি ব্যবহার করতে পছন্দ করি Stream.Builder

আমি একটি সামান্য ফাংশন লিখেছি যা একটি তৈরি করে Collector:

private static <T> Collector<T, Stream.Builder<T>, Stream<T>> copyCollector()
{
    return Collector.of(Stream::builder, Stream.Builder::add, (b1, b2) -> {
        b2.build().forEach(b1);
        return b1;
    }, Stream.Builder::build);
}

তারপরে আমি এমন স্ট্রিমের প্রতিচ্ছবির ব্যবহারের সাথে তাল মিলিয়ে বেশ অনুভব strকরে এমন কোনও স্ট্রিমের অনুলিপি তৈরি করতে পারি str.collect(copyCollector())

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.