কিভাবে একটি স্ট্রিম এটারেটর রূপান্তর করবেন?


468

আমি পুনরুক্তিটিকে একটি স্ট্রিম হিসাবে "দেখার" Iteratorজন্য একটি Streamবা আরও নির্দিষ্টভাবে রূপান্তর করার জন্য একটি সংক্ষিপ্ত উপায় সন্ধান করছি ।

পারফরম্যান্স কারণে, আমি একটি নতুন তালিকায় পুনরাবৃত্তির অনুলিপি এড়াতে চাই:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Collection<String> copyList = new ArrayList<String>();
sourceIterator.forEachRemaining(copyList::add);
Stream<String> targetStream = copyList.stream();

মন্তব্যে কিছু পরামর্শের ভিত্তিতে, আমি ব্যবহার করার চেষ্টাও করেছি Stream.generate:

public static void main(String[] args) throws Exception {
    Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
    Stream<String> targetStream = Stream.generate(sourceIterator::next);
    targetStream.forEach(System.out::println);
}

যাইহোক, আমি একটি পেয়েছি NoSuchElementException(যেহেতু কোনও অনুরোধ নেই hasNext)

Exception in thread "main" java.util.NoSuchElementException
    at java.util.AbstractList$Itr.next(AbstractList.java:364)
    at Main$$Lambda$1/1175962212.get(Unknown Source)
    at java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1351)
    at java.util.Spliterator.forEachRemaining(Spliterator.java:326)
    at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
    at Main.main(Main.java:20)

আমি দিকে তাকিয়ে আছে StreamSupportএবং Collectionsকিন্তু আমি কিছুই খুঁজে পাইনি।



3
@ দিমিত্রিঞ্জজবুর্গ ইউহ আমি কোনও "অসীম" স্ট্রিম তৈরি করতে চাই না।
gontard

1
@ দিমিত্রিঞ্জজবার্গ Stream.generate(iterator::next)কাজ করে?
gontard

1
@ দিমিত্রিঞ্জজবার্গ এটি সীমাবদ্ধ পুনরুদ্ধারের জন্য কাজ করবে না।
Assylias

উত্তর:


543

একটি উপায় হ'ল ইটেটর থেকে একটি স্প্লিটেটর তৈরি করা এবং এটি আপনার স্ট্রিমের ভিত্তি হিসাবে ব্যবহার করুন:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Stream<String> targetStream = StreamSupport.stream(
          Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED),
          false);

একটি বিকল্প যা সম্ভবত আরও পঠনযোগ্য তা হ'ল একটি আইটেবল ব্যবহার করা - এবং একটি আইট্রেটরের কাছ থেকে একটি আইটেবল তৈরি করা ল্যাম্বডাসের সাথে খুব সহজ কারণ ইটেবারে একটি কার্যকরী ইন্টারফেস:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();

Iterable<String> iterable = () -> sourceIterator;
Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);

26
স্ট্রিমটি অলস: কোডটি কেবল স্ট্রিমটিকে আইট্রেটারের সাথে সংযুক্ত করছে তবে টার্মিনাল অপারেশন হওয়া পর্যন্ত আসল পুনরাবৃত্তি ঘটবে না। আপনি যদি এর মধ্যে পুনরাবৃত্তি ব্যবহার করেন তবে আপনি প্রত্যাশিত ফলাফল পাবেন না। উদাহরণস্বরূপ আপনি sourceIterator.next()স্ট্রিমটি ব্যবহারের আগে একটি পরিচয় করিয়ে দিতে পারেন এবং আপনি প্রভাবটি দেখতে পাবেন (প্রথম আইটেমটি স্ট্রিমের দ্বারা দেখা যাবে না)।
Assylias

9
@ অফিসিয়াস, হ্যাঁ এটা সত্যিই দুর্দান্ত! সম্ভবত আপনি ভবিষ্যতের পাঠকদের জন্য এই পুরো ম্যাজিক লাইনটি ব্যাখ্যা করতে পারেন Iterable<String> iterable = () -> sourceIterator;। আমাকে স্বীকার করতে হবে যে এটি বুঝতে আমার কিছুটা সময় লেগেছে।
gontard

7
আমি যা পেয়েছি তা আমার জানা উচিত। যার Iterable<T>একটি FunctionalInterfaceমাত্র বিমূর্ত পদ্ধতি রয়েছে iterator()। সুতরাং () -> sourceIteratorএকটি ল্যামডা অভিব্যক্তি একটি শুরু করতে গিয়ে হয় Iterableএকটি বেনামী বাস্তবায়ন যেমন উদাহরণ হিসেবে বলা যায়।
জিন কোওন

13
আবার, () -> sourceIterator;এর একটি সংক্ষিপ্ত রূপnew Iterable<>() { @Override public Iterator<String> iterator() { return sourceIterator; } }
জিন কোওন

7
@ জিনকোওন এটি কোনও বেনাম শ্রেণীর পক্ষে সংক্ষিপ্ত আকার নয় (কয়েকটি সূক্ষ্ম পার্থক্য রয়েছে যেমন সুযোগ এবং এটি কীভাবে সংকলিত হয়) তবে এটি ক্ষেত্রে একইভাবে আচরণ করে।
assylias

122

21 সংস্করণ থেকে, পেয়ারা গ্রন্থাগার সরবরাহ করে Streams.stream(iterator)

এটার @ assylias এর উত্তর শো



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

এটি দুর্দান্ত তবে… জাভাতে কীভাবে দেশীয় পুনরাবৃত্তকারী এবং স্ট্রিম থাকে… তবে কোনও থেকে অন্যের কাছে যাওয়ার কোনও অন্তর্নির্মিত, সোজা উপায় নেই !? আমার মতে বেশ কিছুটা বাদ।
ড্যান লেন্সকি

92

দুর্দান্ত পরামর্শ! এখানে আমার পুনঃব্যবহারযোগ্য বিষয়:

public class StreamUtils {

    public static <T> Stream<T> asStream(Iterator<T> sourceIterator) {
        return asStream(sourceIterator, false);
    }

    public static <T> Stream<T> asStream(Iterator<T> sourceIterator, boolean parallel) {
        Iterable<T> iterable = () -> sourceIterator;
        return StreamSupport.stream(iterable.spliterator(), parallel);
    }
}

এবং ব্যবহার (স্থিতিশীল হিসাবে স্ট্রিম আমদানি নিশ্চিত করুন):

List<String> aPrefixedStrings = asStream(sourceIterator)
                .filter(t -> t.startsWith("A"))
                .collect(toList());

43

জাভা 9 এ এটি সম্ভব।

Stream.generate(() -> null)
    .takeWhile(x -> iterator.hasNext())
    .map(n -> iterator.next())
    .forEach(System.out::println);

1
সহজ, দক্ষ এবং সাবক্লাসিংয়ের অবলম্বন ছাড়াই - এটি গ্রহণযোগ্য উত্তর হওয়া উচিত!
শহীদগ্লাবিটজ

1
দুর্ভাগ্যক্রমে এগুলি .parallel()স্ট্রিমগুলির সাথে কাজ করে না বলে মনে হয় । এগুলি Spliteratorক্রমবর্ধমান ব্যবহারের জন্য এমনকি কিছুটা ধীরে ধীরে দেখা দেয় ।
টমাস আহলে

এছাড়াও, পুনরুক্তিটি খালি থাকলে প্রথম পদ্ধতিটি ছুঁড়ে দেয়। দ্বিতীয় পদ্ধতিটি আপাতত কাজ করে তবে এটি মানচিত্রে ফাংশনগুলির প্রয়োজনীয়তা লঙ্ঘন করে না এবং রাষ্ট্রহীন হওয়ার জন্য তাই আমি প্রযোজনা কোডে তা করতে দ্বিধা করব।
হ্যান্স-পিটার স্টার

সত্যই, এটি একটি স্বীকৃত উত্তর হওয়া উচিত। যদিও parallelচটকদার হতে পারে সরলতা আশ্চর্যজনক।
সোভেন

11

তৈরি করুন Spliteratorথেকে Iteratorব্যবহার Spliteratorsবর্গ spliterator তৈরি করার জন্য একটির বেশি ফাংশন রয়েছে, উদাহরণস্বরূপ এখানে ব্যবহার করছি spliteratorUnknownSizeযা পুনরুক্তিকারীর প্যারামিটার হিসাবে হচ্ছে, তারপর স্ট্রিম ব্যবহার তৈরিStreamSupport

Spliterator<Model> spliterator = Spliterators.spliteratorUnknownSize(
        iterator, Spliterator.NONNULL);
Stream<Model> stream = StreamSupport.stream(spliterator, false);

1
import com.google.common.collect.Streams;

এবং ব্যবহার Streams.stream(iterator):

Streams.stream(iterator)
       .map(v-> function(v))
       .collect(Collectors.toList());

-4

ব্যবহার Collections.list(iterator).stream()...


6
সংক্ষেপে, এটি খুব ক্ষুদ্রতর হয়।
অলিভিয়ার গ্রাগোয়ার

2
এটি পুরো পুনরাবৃত্তিকে জাভা অবজেক্টে ফোল্ড করবে এবং তারপরে এটি স্ট্রিমে রূপান্তর করবে। আমি এটির পরামর্শ দিচ্ছি না
iec2011007

3
এটি কেবল গণনাগুলির জন্য বলে মনে হচ্ছে, পুনরাবৃত্তিকারী নয়।
16384

1
সাধারণভাবে কোনও ভয়ঙ্কর উত্তর নয়, একটি চিমটিতে কার্যকর, তবে প্রশ্নটিতে পারফরম্যান্স উল্লেখ করা হয়েছে এবং উত্তরটি পারফরম্যান্ট নয়।
টানা স্লেজগাড়ির
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.