একটি প্রিডিকেট দ্বারা একটি স্ট্রিম সীমাবদ্ধ করুন


187

কোনও জাভা 8 স্ট্রিম অপারেশন কি কোনও (সম্ভাব্য অসীম) সীমাবদ্ধ Streamনা করা অবধি প্রথম উপাদান কোনও প্রাক্কলকের সাথে মেলে না?

জাভা 9 তে আমরা takeWhile10 এর চেয়ে কম সংখ্যা মুদ্রণের জন্য নীচের উদাহরণ হিসাবে ব্যবহার করতে পারি ।

IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);

জাভা 8 তে যেমন কোনও অপারেশন নেই, সাধারণভাবে এটি কার্যকর করার সর্বোত্তম উপায় কোনটি?


1
: এ সম্ভবত দরকারী তথ্য stackoverflow.com/q/19803058/248082
nobeh


আমি ভাবছি যে স্থপতিরা কীভাবে এই ব্যবহারের আড়ালে না চলে "" আমরা আসলে এটি কী ব্যবহার করতে পারি "এর মাধ্যমে পেতে পারি। জাভা 8 হিসাবে কেবল স্ট্রিমগুলি বিদ্যমান বিদ্যমান ডেটাস্ট্রাকচারের জন্য কেবল সহায়ক: - /
অ্যান্ডারসেন


জাভা 9 এর সাহায্যে এটি লেখা সহজ হবেIntStream.iterate(1, n->n<10, n->n+1).forEach(System.out::print);
মার্ক Dzaebel

উত্তর:


81

জাভা 8 দিয়ে এই জাতীয় অপারেশনটি সম্ভব হওয়া উচিত Stream, তবে এটি কার্যকরভাবে দক্ষতার সাথে করা সম্ভব নয় - উদাহরণস্বরূপ, আপনি প্রয়োজনীয়ভাবে এ জাতীয় ক্রিয়াকলাপকে সমান্তরাল করতে পারবেন না, কারণ আপনাকে উপাদানগুলি যাতে ক্রমে দেখতে হবে।

এপিআই এটি করার সহজ উপায় সরবরাহ করে না, তবে সম্ভবত সবচেয়ে সহজ উপায়টি হ'ল "নেওয়ার সময়" প্রয়োগকরণটি Stream.iterator()মোড়ানো Iteratorএবং তারপরে একটি Spliteratorএবং তারপরে ফিরে যান Stream। অথবা - হতে পারে - মোড়ানো Spliterator, যদিও এটি বাস্তবায়নের ক্ষেত্রে এটি আর ভাগ করা যায় না।

এখানে একজন অপরীক্ষিত বাস্তবায়ন এর takeWhileএকটি উপর Spliterator:

static <T> Spliterator<T> takeWhile(
    Spliterator<T> splitr, Predicate<? super T> predicate) {
  return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
    boolean stillGoing = true;
    @Override public boolean tryAdvance(Consumer<? super T> consumer) {
      if (stillGoing) {
        boolean hadNext = splitr.tryAdvance(elem -> {
          if (predicate.test(elem)) {
            consumer.accept(elem);
          } else {
            stillGoing = false;
          }
        });
        return hadNext && stillGoing;
      }
      return false;
    }
  };
}

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
   return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}

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

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

আপনার এই উত্তরটি এখনই আপডেট করা উচিত যে জাভা 9 প্রকাশিত হয়েছে।
রেডিওডেফ 4'18

4
না, রেডিওডেফ প্রশ্নটি জাভা 8 সমাধানের জন্য বিশেষভাবে জিজ্ঞাসা করে।
রেনাতো পিছনে

145

অপারেশনগুলি takeWhileএবং dropWhileজেডিকে ৯-এ যুক্ত করা হয়েছে আপনার উদাহরণ কোড

IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);

JDK 9 এর অধীনে সংকলিত হয়ে চালিত হওয়ার সময় আপনি যেমনটি প্রত্যাশা করেছিলেন ঠিক তেমন আচরণ করবে।

জেডিকে 9 মুক্তি পেয়েছে। এটি ডাউনলোডের জন্য এখানে উপলভ্য: http://jdk.java.net/9/


3
JDK9 স্ট্রিম জন্য পূর্বরূপ ডক্স ডাইরেক্ট লিংক, সঙ্গে takeWhile/ dropWhile: download.java.net/jdk9/docs/api/java/util/stream/Stream.html
মাইলস

1
সেখানে কোন কারণে কেন বলা করছি takeWhileএবং dropWhileবদলে limitWhileএবং skipWhileবিদ্যমান API- এর সাথে ঐক্য জন্য?
লুকাস এদার

10
@ লুকাসেদার takeWhileএবং dropWhileস্কেল, পাইথন, গ্রোভী, রুবি, হাস্কেল এবং ক্লোজারে সংঘটিত হয়ে বেশ বিস্তৃত। অসম্পূর্ণতা skipএবং limitদুর্ভাগ্যজনক। সম্ভবত skipএবং limitবলা উচিত ছিল dropএবং বলা উচিত take, তবে এগুলি ততটা স্বজ্ঞাত নয় যদি আপনি হাসকলের সাথে ইতিমধ্যে পরিচিত না হন।
স্টুয়ার্ট

3
@ স্টার্টমার্কস: আমি এটি বুঝতে পেরেছি dropXXXএবং takeXXXআরও জনপ্রিয় পদগুলি কিন্তু আমি ব্যক্তিগতভাবে আরও এসকিউএল-এস্ক limitXXXএবং এর সাথে থাকতে পারি skipXXX। আমি এই নতুন অসম্পূর্ণতাকে শব্দের স্বতন্ত্র পছন্দের চেয়ে অনেক বেশি বিভ্রান্ত মনে করি ... :) (বিটিডাব্লু: স্কালারও রয়েছে drop(int)এবং take(int))
লুকাস এদার

1
হ্যাঁ, আমাকে কেবল প্রযোজনায় জেডকে 9 এ আপগ্রেড করতে দিন। অনেক ডিভস এখনও জেডি কে 8 এ রয়েছে, এই জাতীয় বৈশিষ্ট্যটি শুরু থেকেই স্ট্রিমের সাথে অন্তর্ভুক্ত করা উচিত ছিল।
উইলমল

50

allMatch()একটি সংক্ষিপ্ত-সার্কিট ফাংশন, যাতে আপনি এটি প্রক্রিয়া বন্ধ করতে ব্যবহার করতে পারেন। প্রধান অসুবিধাটি হ'ল আপনাকে দু'বার পরীক্ষা করতে হবে: একবার এটি পরীক্ষা করা উচিত কিনা তা দেখার জন্য, এবং আবার চালিয়ে যেতে হবে কিনা তা দেখার জন্য।

IntStream
    .iterate(1, n -> n + 1)
    .peek(n->{if (n<10) System.out.println(n);})
    .allMatch(n->n < 10);

5
এটি প্রথমে আমার কাছে আপত্তিজনক বলে মনে হয়েছিল (পদ্ধতিটির নাম দেওয়া হয়েছে), তবে ডক্স নিশ্চিত করে যে Stream.allMatch()এটি একটি সংক্ষিপ্ত-সার্কিট ক্রিয়াকলাপ । সুতরাং এটি এমনকি অসীম প্রবাহেও সম্পূর্ণ হবে IntStream.iterate()। অবশ্যই, পূর্ববর্তী ক্ষেত্রে, এটি একটি বোধগম্য অপ্টিমাইজেশন।
বেইলি পার্কার

3
এটি ঝরঝরে, তবে আমি মনে করি না এটি খুব ভালভাবে যোগাযোগ করে যে এর উদ্দেশ্যটি হ'ল দেহ peek। যদি আমি পরের মাসে এটির মুখোমুখি হয়েছি তবে আমি প্রোগ্রামার আমার আগে কেন পরীক্ষা করে কিনা allMatchউত্তরটি উপেক্ষা করে তা অবাক করতে কয়েক মিনিট সময় নেব ।
জোশুয়া গোল্ডবার্গ

10
এই সমাধানটির অসুবিধা হ'ল এটি একটি বুলিয়ান দেয় যাতে আপনি সাধারণভাবে যেমন স্ট্রিমের ফলাফল সংগ্রহ করতে পারবেন না।
নেক্সাস

35

@ স্টুয়ার্টমার্কস এর উত্তর অনুসরণ করে । আমার স্ট্রিমএক্স লাইব্রেরিতে takeWhileঅপারেশন রয়েছে যা বর্তমান জেডিকে -9 বাস্তবায়নের সাথে সামঞ্জস্যপূর্ণ। জেডিকে -9 এর অধীনে চলার সময় এটি কেবল জেডিকে বাস্তবায়নের জন্য প্রেরণ করবে ( MethodHandle.invokeExactযার মাধ্যমে সত্যই দ্রুত)। জেডিকে -২ এর অধীনে চলাকালীন, "পলিফিল" বাস্তবায়ন ব্যবহৃত হবে। সুতরাং আমার গ্রন্থাগারটি ব্যবহার করে সমস্যার সমাধান করা যেতে পারে:

IntStreamEx.iterate(1, n -> n + 1)
           .takeWhile(n -> n < 10)
           .forEach(System.out::println);

আপনি এটিকে স্ট্রিমেক্স ক্লাসের জন্য বাস্তবায়ন করেননি কেন?
সোমগুয়ে

@ সোমগুয়ে আমি এটি বাস্তবায়ন করেছি।
তাগীর ভালিভ


11

আপডেট: জাভা 9 Streamএখন একটি টিকহাইল পদ্ধতি নিয়ে আসে ।

হ্যাকস বা অন্যান্য সমাধানের প্রয়োজন নেই। শুধু যে ব্যবহার!


আমি নিশ্চিত যে এটির উপর ব্যাপক উন্নতি করা যেতে পারে: (কেউ এটিকে থ্রেড-নিরাপদ করতে পারে)

Stream<Integer> stream = Stream.iterate(0, n -> n + 1);

TakeWhile.stream(stream, n -> n < 10000)
         .forEach(n -> System.out.print((n == 0 ? "" + n : "," + n)));

নিশ্চিতভাবে একটি হ্যাক ... মার্জিত নয় - তবে এটি কার্যকর ~: D

class TakeWhile<T> implements Iterator<T> {

    private final Iterator<T> iterator;
    private final Predicate<T> predicate;
    private volatile T next;
    private volatile boolean keepGoing = true;

    public TakeWhile(Stream<T> s, Predicate<T> p) {
        this.iterator = s.iterator();
        this.predicate = p;
    }

    @Override
    public boolean hasNext() {
        if (!keepGoing) {
            return false;
        }
        if (next != null) {
            return true;
        }
        if (iterator.hasNext()) {
            next = iterator.next();
            keepGoing = predicate.test(next);
            if (!keepGoing) {
                next = null;
            }
        }
        return next != null;
    }

    @Override
    public T next() {
        if (next == null) {
            if (!hasNext()) {
                throw new NoSuchElementException("Sorry. Nothing for you.");
            }
        }
        T temp = next;
        next = null;
        return temp;
    }

    public static <T> Stream<T> stream(Stream<T> s, Predicate<T> p) {
        TakeWhile tw = new TakeWhile(s, p);
        Spliterator split = Spliterators.spliterator(tw, Integer.MAX_VALUE, Spliterator.ORDERED);
        return StreamSupport.stream(split, false);
    }

}

8

আপনি java8 + rxjava ব্যবহার করতে পারেন ।

import java.util.stream.IntStream;
import rx.Observable;


// Example 1)
IntStream intStream  = IntStream.iterate(1, n -> n + 1);
Observable.from(() -> intStream.iterator())
    .takeWhile(n ->
          {
                System.out.println(n);
                return n < 10;
          }
    ).subscribe() ;


// Example 2
IntStream intStream  = IntStream.iterate(1, n -> n + 1);
Observable.from(() -> intStream.iterator())
    .takeWhile(n -> n < 10)
    .forEach( n -> System.out.println(n));

6

আসলে জাভা 8 তে এটি করার জন্য 2 টি অতিরিক্ত উপায় রয়েছে কোনও অতিরিক্ত লাইব্রেরি বা জাভা 9 ব্যবহার না করে।

আপনি যদি কনসোলে 2 থেকে 20 নম্বর মুদ্রণ করতে চান তবে আপনি এটি করতে পারেন:

IntStream.iterate(2, (i) -> i + 2).peek(System.out::println).allMatch(i -> i < 20);

অথবা

IntStream.iterate(2, (i) -> i + 2).peek(System.out::println).anyMatch(i -> i >= 20);

আউটপুট উভয় ক্ষেত্রে:

2
4
6
8
10
12
14
16
18
20

কেউ এখনও কোনও ম্যাচ উল্লেখ করেনি। এই পোস্টের কারণ এটি।


5

এটি জেডিকে 9 java.util.stream.Stream.takeWhile (ভবিষ্যদ্বাণী) থেকে অনুলিপি করা উত্স। জেডিকে 8 নিয়ে কাজ করার জন্য কিছুটা পার্থক্য।

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> p) {
    class Taking extends Spliterators.AbstractSpliterator<T> implements Consumer<T> {
        private static final int CANCEL_CHECK_COUNT = 63;
        private final Spliterator<T> s;
        private int count;
        private T t;
        private final AtomicBoolean cancel = new AtomicBoolean();
        private boolean takeOrDrop = true;

        Taking(Spliterator<T> s) {
            super(s.estimateSize(), s.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED));
            this.s = s;
        }

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            boolean test = true;
            if (takeOrDrop &&               // If can take
                    (count != 0 || !cancel.get()) && // and if not cancelled
                    s.tryAdvance(this) &&   // and if advanced one element
                    (test = p.test(t))) {   // and test on element passes
                action.accept(t);           // then accept element
                return true;
            } else {
                // Taking is finished
                takeOrDrop = false;
                // Cancel all further traversal and splitting operations
                // only if test of element failed (short-circuited)
                if (!test)
                    cancel.set(true);
                return false;
            }
        }

        @Override
        public Comparator<? super T> getComparator() {
            return s.getComparator();
        }

        @Override
        public void accept(T t) {
            count = (count + 1) & CANCEL_CHECK_COUNT;
            this.t = t;
        }

        @Override
        public Spliterator<T> trySplit() {
            return null;
        }
    }
    return StreamSupport.stream(new Taking(stream.spliterator()), stream.isParallel()).onClose(stream::close);
}

4

Ints এ এখানে একটি সংস্করণ দেওয়া হয়েছে - যেমন প্রশ্নে জিজ্ঞাসা করা হয়েছে।

ব্যবহার:

StreamUtil.takeWhile(IntStream.iterate(1, n -> n + 1), n -> n < 10);

স্ট্রিমটিলের জন্য এখানে কোড:

import java.util.PrimitiveIterator;
import java.util.Spliterators;
import java.util.function.IntConsumer;
import java.util.function.IntPredicate;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;

public class StreamUtil
{
    public static IntStream takeWhile(IntStream stream, IntPredicate predicate)
    {
        return StreamSupport.intStream(new PredicateIntSpliterator(stream, predicate), false);
    }

    private static class PredicateIntSpliterator extends Spliterators.AbstractIntSpliterator
    {
        private final PrimitiveIterator.OfInt iterator;
        private final IntPredicate predicate;

        public PredicateIntSpliterator(IntStream stream, IntPredicate predicate)
        {
            super(Long.MAX_VALUE, IMMUTABLE);
            this.iterator = stream.iterator();
            this.predicate = predicate;
        }

        @Override
        public boolean tryAdvance(IntConsumer action)
        {
            if (iterator.hasNext()) {
                int value = iterator.nextInt();
                if (predicate.test(value)) {
                    action.accept(value);
                    return true;
                }
            }

            return false;
        }
    }
}

2

AbacusUtil লাইব্রেরি পেতে যান । এটি আপনার পছন্দসই সঠিক API সরবরাহ করে এবং আরও অনেক কিছু:

IntStream.iterate(1, n -> n + 1).takeWhile(n -> n < 10).forEach(System.out::println);

ঘোষণা : আমি অ্যাবাকাসটিলের বিকাশকারী।


0

আপনি একটি সংক্ষিপ্ত-সার্কিট টার্মিনাল অপারেশন ব্যতীত কোনও স্ট্রিমটিকে বাতিল করতে পারবেন না, যার ফলে কিছু স্ট্রিম মান তাদের মান নির্বিশেষে অপসারণ করা হবে। তবে আপনি যদি কেবল একটি স্ট্রিমের অপারেশন এড়াতে চান তবে আপনি স্ট্রিমে একটি রূপান্তর এবং ফিল্টার যুক্ত করতে পারেন:

import java.util.Objects;

class ThingProcessor
{
    static Thing returnNullOnCondition(Thing thing)
    {    return( (*** is condition met ***)? null : thing);    }

    void processThings(Collection<Thing> thingsCollection)
    {
        thingsCollection.stream()
        *** regular stream processing ***
        .map(ThingProcessor::returnNullOnCondition)
        .filter(Objects::nonNull)
        *** continue stream processing ***
    }
} // class ThingProcessor

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


কিছু খোঁজখবর করে যে কিছু বেনামে আমার উত্তরটি কেন তা না বলেই নষ্ট করেছে me সুতরাং আমি বা অন্য কোনও পাঠকই জানেন না যে আমার উত্তরটিতে কী দোষ রয়েছে। তাদের ন্যায্যতার অনুপস্থিতিতে আমি তাদের সমালোচনাকে অবৈধ বলে বিবেচনা করব এবং পোস্ট হিসাবে আমার উত্তরটি সঠিক বলে বিবেচিত হবে।
ম্যাথু

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

0

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

import java.util.stream.IntStream;

import io.netty.util.internal.ThreadLocalRandom;

class TrialStreamMatch {

public static void main(String[] args) {        
    if(!IntStream.range(1,3).anyMatch(integ -> webServiceCall(integ))){
         //Code for sending email notifications
    }
}

public static boolean webServiceCall(int i){
    //For time being, I have written a code for generating boolean randomly
    //This whole piece needs to be replaced by actual web-service client code
    boolean bool = ThreadLocalRandom.current().nextBoolean();
    System.out.println("Iteration index :: "+i+" bool :: "+bool);

    //Return success status -- true or false
    return bool;
}

0

আপনি যদি সম্পাদন করবেন তার সঠিক পরিমাণটি জানেন তবে আপনি এটি করতে পারেন

IntStream
          .iterate(1, n -> n + 1)
          .limit(10)
          .forEach(System.out::println);

1
যদিও এটি লেখকদের প্রশ্নের উত্তর দিতে পারে, এতে কিছু ব্যাখ্যাকারী শব্দ এবং ডকুমেন্টেশনের লিঙ্কের অভাব রয়েছে। কাঁচা কোড স্নিপেটগুলি এর চারপাশে কিছু বাক্যাংশ ব্যতীত খুব বেশি কার্যকর নয়। আপনি কীভাবে একটি ভাল উত্তর লিখতে পারেন তা খুব সহায়ক। আপনার উত্তর সম্পাদনা করুন।
হেলো

0
    IntStream.iterate(1, n -> n + 1)
    .peek(System.out::println) //it will be executed 9 times
    .filter(n->n>=9)
    .findAny();

চূড়ান্ত পরিবর্তে আপনি চূড়ান্ত অবজেক্ট বা বার্তা ফেরত দিতে মানচিত্রটওবজ ব্যবহার করতে পারেন

    IntStream.iterate(1, n -> n + 1)
    .mapToObj(n->{   //it will be executed 9 times
            if(n<9)
                return "";
            return "Loop repeats " + n + " times";});
    .filter(message->!message.isEmpty())
    .findAny()
    .ifPresent(System.out::println);

-2

আপনার যদি পৃথক সমস্যা হয় তবে বিভিন্ন সমাধানের প্রয়োজন হতে পারে তবে আপনার বর্তমান সমস্যার জন্য আমি কেবল সাথে যাব:

IntStream
    .iterate(1, n -> n + 1)
    .limit(10)
    .forEach(System.out::println);

-2

কিছুটা সাময়িক বিষয় হতে পারে তবে আমাদের এটির List<T>পরিবর্তে যা আছে তা Stream<T>

প্রথমে আপনার একটি ব্যবহার takeপদ্ধতি থাকা দরকার। এই পদ্ধতিতে প্রথম nউপাদানগুলি লাগে :

static <T> List<T> take(List<T> l, int n) {
    if (n <= 0) {
        return newArrayList();
    } else {
        int takeTo = Math.min(Math.max(n, 0), l.size());
        return l.subList(0, takeTo);
    }
}

এটা ঠিক মত কাজ করে scala.List.take

    assertEquals(newArrayList(1, 2, 3), take(newArrayList(1, 2, 3, 4, 5), 3));
    assertEquals(newArrayList(1, 2, 3), take(newArrayList(1, 2, 3), 5));

    assertEquals(newArrayList(), take(newArrayList(1, 2, 3), -1));
    assertEquals(newArrayList(), take(newArrayList(1, 2, 3), 0));

এখন এটি takeWhileউপর ভিত্তি করে একটি পদ্ধতি লিখতে মোটামুটি সহজ হবেtake

static <T> List<T> takeWhile(List<T> l, Predicate<T> p) {
    return l.stream().
            filter(p.negate()).findFirst(). // find first element when p is false
            map(l::indexOf).        // find the index of that element
            map(i -> take(l, i)).   // take up to the index
            orElse(l);  // return full list if p is true for all elements
}

এটি এর মতো কাজ করে:

    assertEquals(newArrayList(1, 2, 3), takeWhile(newArrayList(1, 2, 3, 4, 3, 2, 1), i -> i < 4));

এই প্রয়োগটি কয়েকবার তালিকাটিকে আংশিকভাবে পুনরাবৃত্তি করে তবে এটি অ্যাড O(n^2)অপারেশন যুক্ত করে না। আশা করি তা গ্রহণযোগ্য।


-3

এটি প্রয়োগ করে আমার কাছে আরও একটি দ্রুত সমাধান রয়েছে (যা বাস্তবে অশুচি, তবে আপনি ধারণাটি পান):

public static void main(String[] args) {
    System.out.println(StreamUtil.iterate(1, o -> o + 1).terminateOn(15)
            .map(o -> o.toString()).collect(Collectors.joining(", ")));
}

static interface TerminatedStream<T> {
    Stream<T> terminateOn(T e);
}

static class StreamUtil {
    static <T> TerminatedStream<T> iterate(T seed, UnaryOperator<T> op) {
        return new TerminatedStream<T>() {
            public Stream<T> terminateOn(T e) {
                Builder<T> builder = Stream.<T> builder().add(seed);
                T current = seed;
                while (!current.equals(e)) {
                    current = op.apply(current);
                    builder.add(current);
                }
                return builder.build();
            }
        };
    }
}

2
আপনি পুরো স্ট্রিমটি আগে থেকেই মূল্যায়ন করছেন ! এবং যদি তা currentনা হয় তবে .equals(e)আপনি একটি অন্তহীন লুপ পাবেন। উভয়ই যদি আপনি পরবর্তীকালে প্রয়োগ করেন তবে .limit(1)। এটি 'অপরিষ্কার' থেকে অনেক খারাপ ।
চার্লি

-3

এখানে কেবল জাভা স্ট্রিমের লাইব্রেরি ব্যবহার করার চেষ্টা করা হচ্ছে।

        IntStream.iterate(0, i -> i + 1)
        .filter(n -> {
                if (n < 10) {
                    System.out.println(n);
                    return false;
                } else {
                    return true;
                }
            })
        .findAny();

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