वहाँ जावा 8 में सूचकांक के साथ एक धारा पर पुनरावृति करने के लिए एक संक्षिप्त तरीका है?


382

क्या स्ट्रीम में इंडेक्स तक पहुंच प्राप्त करते हुए एक धारा पर पुनरावृति करने का एक संक्षिप्त तरीका है?

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

List<String> nameList;
Stream<Integer> indices = intRange(1, names.length).boxed();
nameList = zip(indices, stream(names), SimpleEntry::new)
        .filter(e -> e.getValue().length() <= e.getKey())
        .map(Entry::getValue)
        .collect(toList());

जो वहां दिए गए LINQ उदाहरण की तुलना में निराशाजनक लगता है

string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
var nameList = names.Where((c, index) => c.Length <= index + 1).ToList();

क्या अधिक संक्षिप्त तरीका है?

इसके अलावा ऐसा लगता है कि ज़िप या तो हटा दिया गया है या हटा दिया गया है ...


2
क्या है intRange()? जावा 8 में अब तक इस पद्धति का विस्तार नहीं हुआ है।
रोहित जैन

@ रोहितजैन शायद IntStream.rangeClosed(x, y)
assylias

2
एक पक्ष की टिप्पणी के रूप में, चुनौती 4 बेहतर दिखता है (IMO)List<String> allCities = map.values().stream().flatMap(list -> list.stream()).collect(Collectors.toList());
19

3
हां, zipप्रायोगिक दो-मूल्यवान धाराओं के साथ हटा दिया गया था, जिसे विभिन्न रूप से कहा जाता है BiStreamया MapStream। मुख्य समस्या यह है कि इसे प्रभावी ढंग से करने के लिए जावा को वास्तव में एक संरचनात्मक रूप से टाइप की गई जोड़ी (या ट्यूपल) प्रकार की आवश्यकता है। एक को खो देना, एक सामान्य जोड़ी या टपल क्लास बनाना आसान है - यह कई बार किया गया है - लेकिन वे सभी एक ही प्रकार से मिटा देते हैं।
स्टुअर्ट मार्क्स

3
ओह, जेनेरिक पेयर या टपल क्लास के साथ एक और समस्या यह है कि इसके लिए सभी प्राइमेटिव को बॉक्सिंग की आवश्यकता होती है।
स्टुअर्ट मार्क्स

जवाबों:


435

सबसे साफ तरीका सूचकांकों की एक धारा से शुरू होता है:

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
IntStream.range(0, names.length)
         .filter(i -> names[i].length() <= i)
         .mapToObj(i -> names[i])
         .collect(Collectors.toList());

परिणामी सूची में केवल "एरिक" शामिल है।


जब आप छोरों के लिए उपयोग किए जाते हैं, तो एक विकल्प जो एक परिचित वस्तु का उपयोग करके तदर्थ काउंटर बनाए रखने के लिए होगा, उदाहरण के लिए AtomicInteger:

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
AtomicInteger index = new AtomicInteger();
List<String> list = Arrays.stream(names)
                          .filter(n -> n.length() <= index.incrementAndGet())
                          .collect(Collectors.toList());

ध्यान दें कि एक समानांतर धारा पर बाद के तरीके का उपयोग करने से टूट सकता है क्योंकि आइटमों को स्वाभाविक रूप से "क्रम में" संसाधित नहीं किया जाएगा


28
एटोमिक्स का उपयोग इस तरह से समानांतर धाराओं के साथ समस्याग्रस्त है। सबसे पहले, तत्वों के प्रसंस्करण का क्रम आवश्यक नहीं होगा कि प्रारंभिक सरणी में तत्व किस क्रम में होते हैं। इस प्रकार, परमाणु का उपयोग करके सौंपा गया "इंडेक्स" वास्तविक सरणी इंडेक्स से मेल नहीं खाएगा। दूसरा, जब एटॉमिक्स थ्रेड-सुरक्षित होते हैं, तो आप परमाणु को अपडेट करने वाले कई थ्रेड्स के बीच विवाद का सामना कर सकते हैं, समानता की मात्रा को कम कर सकते हैं।
स्टुअर्ट मार्क्स

1
मैंने @assylias द्वारा एक के समान एक समाधान विकसित किया। समस्याग्रस्त को समानांतर धारा @StuartMarks के साथ चक्कर लगाने के लिए, मैं पहली बार दिए गए समानांतर धारा अनुक्रमिक बनाता हूं, मानचित्रण करता हूं और समानांतर स्थिति को पुनर्स्थापित करता हूं। public static <T> Stream<Tuple2<Integer, T>> zipWithIndex(Stream<T> stream) { final AtomicInteger index = new AtomicInteger(); final Function<T, Tuple2<Integer, T>> zipper = e -> Tuples.of(index.getAndIncrement(), e); if (stream.isParallel()) { return stream.sequential().map(zipper).parallel(); } else { return stream.map(zipper); } }
डेनियल डिट्रिच

4
@DanielDietrich अगर आपको लगता है कि यह सवाल हल करता है तो आपको इसे एक टिप्पणी के बजाय उत्तर के रूप में पोस्ट करना चाहिए (और कोड अधिक पठनीय भी होगा!)।
असेलिया

3
@DanielDietrich क्षमा करें, अगर मैं उस कोड को सही ढंग से पढ़ रहा हूं, तो यह काम नहीं करेगा। आपके पास समानांतर बनाम अनुक्रमिक में चलने वाली पाइपलाइन के विभिन्न खंड नहीं हो सकते। टर्मिनल ऑपरेशन शुरू होने पर केवल अंतिम parallelया sequentialसम्मानित किया जाता है।
स्टुअर्ट मार्क्स

4
न्याय के लिए, @ स्टुअर्ट के जवाब से "सबसे साफ रास्ता" चुराया गया था।
वडज़िम

70

जावा 8 स्ट्रीम एपीआई में स्ट्रीम तत्व के सूचकांक के साथ-साथ धाराओं को एक साथ जोड़ने की क्षमता का अभाव है। यह दुर्भाग्यपूर्ण है, क्योंकि यह कुछ अनुप्रयोगों (जैसे LINQ चुनौतियों) को और अधिक कठिन बना देता है, क्योंकि वे अन्यथा कठिन होते हैं।

हालांकि, अक्सर वर्कअराउंड होते हैं। आमतौर पर यह एक पूर्णांक सीमा के साथ धारा को "ड्राइविंग" करके किया जा सकता है, और इस तथ्य का लाभ उठाते हुए कि मूल तत्व अक्सर एक सरणी में या सूचकांक द्वारा सुलभ संग्रह में होते हैं। उदाहरण के लिए, चैलेंज 2 समस्या को इस तरह से हल किया जा सकता है:

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};

List<String> nameList =
    IntStream.range(0, names.length)
        .filter(i -> names[i].length() <= i)
        .mapToObj(i -> names[i])
        .collect(toList());

जैसा कि मैंने ऊपर उल्लेख किया है, यह इस तथ्य का लाभ उठाता है कि डेटा स्रोत (नाम सरणी) सीधे अनुक्रमित है। यदि ऐसा नहीं होता, तो यह तकनीक काम नहीं करती।

मैं मानता हूँ कि यह चुनौती 2 के इरादे को संतुष्ट नहीं करता है। फिर भी यह समस्या को प्रभावी ढंग से हल करता है।

संपादित करें

मेरे पिछले कोड का उदाहरण flatMapफ़िल्टर और मानचित्र संचालन को फ्यूज करने के लिए इस्तेमाल किया गया था, लेकिन यह बोझिल था और कोई फायदा नहीं हुआ। मैंने होल्गर की टिप्पणी के अनुसार उदाहरण को अद्यतन किया है।


7
कैसे के बारे में IntStream.range(0, names.length).filter(i->names[i].length()<=i).mapToObj(i->names[i])? यह मुक्केबाजी के बिना काम करता है ...
होल्गर

1
हम्म, हाँ, मुझे क्यों लगा कि मुझे flatMapवैसे भी उपयोग करने की आवश्यकता है ?
स्टुअर्ट मार्क्स

2
अंत में इस पर फिर से गौर करना ... मैंने शायद इसका उपयोग किया flatMapक्योंकि यह एक फिल्टर में एक फिल्टरिंग और मैपिंग ऑपरेशन को फ़्यूज़ करता है, लेकिन यह वास्तव में कोई लाभ नहीं देता है। मैं उदाहरण संपादित करूंगा।
स्टुअर्ट मार्क्स

Stream.of (Array) एक सरणी के लिए एक स्ट्रीम इंटरफ़ेस बनाएगा। प्रभावी रूप से इसे Stream.of( names ).filter( n -> n.length() <= 1).collect( Collectors.toList() );कम अनबॉक्सिंग, और कम मेमोरी आवंटन में बनाना; जैसा कि हम अब एक रेंज स्ट्रीम नहीं बना रहे हैं।
कोड आईज

44

अमरूद 21 के बाद से, आप उपयोग कर सकते हैं

Streams.mapWithIndex()

उदाहरण ( आधिकारिक डॉक से ):

Streams.mapWithIndex(
    Stream.of("a", "b", "c"),
    (str, index) -> str + ":" + index)
) // will return Stream.of("a:0", "b:1", "c:2")

3
इसके अलावा, अमरूद के लोगों ने अभी तक forEachWithIndex (किसी फंक्शन के बजाय एक उपभोक्ता को लेना) को लागू नहीं किया है, लेकिन यह एक असाइन किया गया मुद्दा है: github.com/google/guava/issues/2913
जॉन ग्लासमी

25

मैंने अपनी परियोजना में निम्नलिखित समाधान का उपयोग किया है। मुझे लगता है कि यह उत्परिवर्तनीय वस्तुओं या पूर्णांक श्रेणियों का उपयोग करने से बेहतर है।

import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Collector.Characteristics;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static java.util.Objects.requireNonNull;


public class CollectionUtils {
    private CollectionUtils() { }

    /**
     * Converts an {@link java.util.Iterator} to {@link java.util.stream.Stream}.
     */
    public static <T> Stream<T> iterate(Iterator<? extends T> iterator) {
        int characteristics = Spliterator.ORDERED | Spliterator.IMMUTABLE;
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, characteristics), false);
    }

    /**
     * Zips the specified stream with its indices.
     */
    public static <T> Stream<Map.Entry<Integer, T>> zipWithIndex(Stream<? extends T> stream) {
        return iterate(new Iterator<Map.Entry<Integer, T>>() {
            private final Iterator<? extends T> streamIterator = stream.iterator();
            private int index = 0;

            @Override
            public boolean hasNext() {
                return streamIterator.hasNext();
            }

            @Override
            public Map.Entry<Integer, T> next() {
                return new AbstractMap.SimpleImmutableEntry<>(index++, streamIterator.next());
            }
        });
    }

    /**
     * Returns a stream consisting of the results of applying the given two-arguments function to the elements of this stream.
     * The first argument of the function is the element index and the second one - the element value. 
     */
    public static <T, R> Stream<R> mapWithIndex(Stream<? extends T> stream, BiFunction<Integer, ? super T, ? extends R> mapper) {
        return zipWithIndex(stream).map(entry -> mapper.apply(entry.getKey(), entry.getValue()));
    }

    public static void main(String[] args) {
        String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};

        System.out.println("Test zipWithIndex");
        zipWithIndex(Arrays.stream(names)).forEach(entry -> System.out.println(entry));

        System.out.println();
        System.out.println("Test mapWithIndex");
        mapWithIndex(Arrays.stream(names), (Integer index, String name) -> index+"="+name).forEach((String s) -> System.out.println(s));
    }
}

+1 - एक फ़ंक्शन को लागू करने में सक्षम था जो प्रत्येक एन इंडेक्स का उपयोग करने वाले एक तत्व को सम्मिलित करता है StreamSupport.stream()और एक कस्टम पुनरावृत्ति करता है।
ACH

13

प्रोटॉनपैक के अलावा, जूसर के सीक यह कार्यक्षमता प्रदान करता है (और विस्तार पुस्तकालयों द्वारा जो इस पर निर्माण करते हैं जैसे कि साइक्लोप्स-रिएक्शन , मैं इस लाइब्रेरी का लेखक हूं)।

Seq.seq(Stream.of(names)).zipWithIndex()
                         .filter( namesWithIndex -> namesWithIndex.v1.length() <= namesWithIndex.v2 + 1)
                         .toList();

Seq भी Seq.of (नाम) का समर्थन करता है और कवर के तहत एक JDK स्ट्रीम का निर्माण करेगा।

सरल-प्रतिक्रिया समतुल्य समान दिखाई देगी

 LazyFutureStream.of(names)
                 .zipWithIndex()
                 .filter( namesWithIndex -> namesWithIndex.v1.length() <= namesWithIndex.v2 + 1)
                 .toList();

सरल-प्रतिक्रिया संस्करण अतुल्यकालिक / समवर्ती प्रसंस्करण के लिए अधिक अनुरूप है।


जॉन मैंने आज आपकी लाइब्रेरी देखी, मैं चकित और भ्रमित दोनों हूँ।
GOXR3PLUS

12

बस पूर्णता के लिए यहाँ समाधान मेरे StreamEx पुस्तकालय शामिल है:

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
EntryStream.of(names)
    .filterKeyValue((idx, str) -> str.length() <= idx+1)
    .values().toList();

यहां हम एक ऐसा निर्माण करते हैं EntryStream<Integer, String>जो Stream<Entry<Integer, String>>कुछ विशिष्ट कार्यों को जोड़ता है और जैसे filterKeyValueया values। साथ ही toList()शॉर्टकट का उपयोग किया जाता है।


अच्छा कार्य; वहाँ के लिए एक शॉर्टकट है .forEach(entry -> {}) ?
स्टीव ओह

2
@SteveOh अगर मैं समझता हूं कि आप सही ढंग से सवाल करते हैं, तो हां, आप लिख सकते हैं .forKeyValue((key, value) -> {})
टैगिर वलेव

8

जब स्ट्रीम सूची या सरणी (और आप आकार जानते हैं) से बना है, तो मुझे यहां समाधान मिला। लेकिन क्या होगा अगर स्ट्रीम अज्ञात आकार के साथ है? इस मामले में इस संस्करण की कोशिश करें:

public class WithIndex<T> {
    private int index;
    private T value;

    WithIndex(int index, T value) {
        this.index = index;
        this.value = value;
    }

    public int index() {
        return index;
    }

    public T value() {
        return value;
    }

    @Override
    public String toString() {
        return value + "(" + index + ")";
    }

    public static <T> Function<T, WithIndex<T>> indexed() {
        return new Function<T, WithIndex<T>>() {
            int index = 0;
            @Override
            public WithIndex<T> apply(T t) {
                return new WithIndex<>(index++, t);
            }
        };
    }
}

उपयोग:

public static void main(String[] args) {
    Stream<String> stream = Stream.of("a", "b", "c", "d", "e");
    stream.map(WithIndex.indexed()).forEachOrdered(e -> {
        System.out.println(e.index() + " -> " + e.value());
    });
}

6

एक सूची के साथ आप कोशिश कर सकते हैं

List<String> strings = new ArrayList<>(Arrays.asList("First", "Second", "Third", "Fourth", "Fifth")); // An example list of Strings
strings.stream() // Turn the list into a Stream
    .collect(HashMap::new, (h, o) -> h.put(h.size(), o), (h, o) -> {}) // Create a map of the index to the object
        .forEach((i, o) -> { // Now we can use a BiConsumer forEach!
            System.out.println(String.format("%d => %s", i, o));
        });

आउटपुट:

0 => First
1 => Second
2 => Third
3 => Fourth
4 => Fifth

1
वास्तव में एक अच्छा विचार है, लेकिन तार :: indexOf थोड़ा महंगा हो सकता है। मेरा सुझाव इसके बजाय उपयोग करना है: .collect (HashMap :: new, (h, s) -> h.put (h.size (), s), (h, s) -> {}) । आप बस इंडेक्स बनाने के लिए आकार () विधि का उपयोग कर सकते हैं।
gil.fernandes

@ gil.fernandes सुझाव के लिए धन्यवाद। मैं संपादन करूँगा।
V0idst4r

3

Streamअनुक्रमणिका तक पहुँच प्राप्त करने के दौरान इसे पुनरावृत्त करने का कोई तरीका नहीं है क्योंकि कोई Streamभी इसके विपरीत है Collectionदस्तावेज़Stream में बताए अनुसार डेटा को एक स्थान से दूसरे स्थान तक ले जाने के लिए A केवल एक पाइपलाइन है :

कोई भंडारण नहीं। एक धारा एक डेटा संरचना नहीं है जो तत्वों को संग्रहीत करती है; इसके बजाय, वे कम्प्यूटेशनल ऑपरेशन की पाइपलाइन के माध्यम से एक स्रोत (जो एक डेटा संरचना, एक जनरेटर, एक IO चैनल आदि) से मान ले सकते हैं।

बेशक, जैसा कि आप अपने प्रश्न में संकेत देते हैं, आप हमेशा अपने Stream<V>को Collection<V>ऐसे में परिवर्तित कर सकते हैं , जैसे कि List<V>, जिसमें आपको अनुक्रमणिका तक पहुंच प्राप्त होगी।


2
यह अन्य भाषाओं / उपकरणों में उपलब्ध है। यह केवल नक्शा समारोह के लिए पारित एक वृद्धि मूल्य है
ली कैंपबेल

दस्तावेज़ से आपका लिंक टूट गया है।
उस्मान मुतावकिल

3

Https://github.com/poetix/protonpack के साथ आप उस ज़िप को कर सकते हैं:

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

List<String> nameList;
Stream<Integer> indices = IntStream.range(0, names.length).boxed(); 

nameList = StreamUtils.zip(indices, stream(names),SimpleEntry::new)
        .filter(e -> e.getValue().length() <= e.getKey()).map(Entry::getValue).collect(toList());                   

System.out.println(nameList);

3

आप किसी तृतीय-पक्ष लाइब्रेरी का उपयोग कोई आपत्ति नहीं है, ग्रहण संग्रह है zipWithIndexऔर forEachWithIndexकई प्रकार भर में उपयोग के लिए उपलब्ध। यहाँ इस चुनौती के समाधान के लिए JDK प्रकारों और ग्रहण संग्रहों दोनों प्रकारों का उपयोग किया गया है zipWithIndex

String[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
ImmutableList<String> expected = Lists.immutable.with("Erik");
Predicate<Pair<String, Integer>> predicate =
    pair -> pair.getOne().length() <= pair.getTwo() + 1;

// JDK Types
List<String> strings1 = ArrayIterate.zipWithIndex(names)
    .collectIf(predicate, Pair::getOne);
Assert.assertEquals(expected, strings1);

List<String> list = Arrays.asList(names);
List<String> strings2 = ListAdapter.adapt(list)
    .zipWithIndex()
    .collectIf(predicate, Pair::getOne);
Assert.assertEquals(expected, strings2);

// Eclipse Collections types
MutableList<String> mutableNames = Lists.mutable.with(names);
MutableList<String> strings3 = mutableNames.zipWithIndex()
    .collectIf(predicate, Pair::getOne);
Assert.assertEquals(expected, strings3);

ImmutableList<String> immutableNames = Lists.immutable.with(names);
ImmutableList<String> strings4 = immutableNames.zipWithIndex()
    .collectIf(predicate, Pair::getOne);
Assert.assertEquals(expected, strings4);

MutableList<String> strings5 = mutableNames.asLazy()
    .zipWithIndex()
    .collectIf(predicate, Pair::getOne, Lists.mutable.empty());
Assert.assertEquals(expected, strings5);

यहाँ एक समाधान का उपयोग कर रहा है forEachWithIndex

MutableList<String> mutableNames =
    Lists.mutable.with("Sam", "Pamela", "Dave", "Pascal", "Erik");
ImmutableList<String> expected = Lists.immutable.with("Erik");

List<String> actual = Lists.mutable.empty();
mutableNames.forEachWithIndex((name, index) -> {
        if (name.length() <= index + 1)
            actual.add(name);
    });
Assert.assertEquals(expected, actual);

यदि आप लैम्ब्डा को गुमनाम आंतरिक कक्षाओं में बदलते हैं, तो ये सभी कोड उदाहरण जावा 5 - 7 में भी काम करेंगे।

नोट: मैं एक्लिप्स कलेक्शंस के लिए कमिट हूं


2

यदि आप Vavr (जिसे पहले Javaslang के रूप में जाना जाता है) का उपयोग करते हैं, तो आप समर्पित पद्धति का लाभ उठा सकते हैं:

Stream.of("A", "B", "C")
  .zipWithIndex();

यदि हम सामग्री का प्रिंट आउट लेते हैं, तो हम कुछ दिलचस्प देखेंगे:

Stream((A, 0), ?)

ऐसा इसलिए है क्योंकि Streamsआलसी हैं और हमें स्ट्रीम में अगले आइटमों के बारे में कोई सुराग नहीं है।


1

यदि आप एक विधेय के आधार पर एक सूचकांक प्राप्त करने की कोशिश कर रहे हैं, तो यह कोशिश करें:

यदि आप केवल पहले सूचकांक की परवाह करते हैं:

OptionalInt index = IntStream.range(0, list.size())
    .filter(i -> list.get(i) == 3)
    .findFirst();

या यदि आप कई इंडेक्स ढूंढना चाहते हैं:

IntStream.range(0, list.size())
   .filter(i -> list.get(i) == 3)
   .collect(Collectors.toList());

.orElse(-1);यदि आप इसे नहीं पाते हैं तो उस स्थिति में जोड़ें जब आप कोई मान लौटना चाहते हैं।


1

यहाँ AbacusUtil द्वारा कोड दिया गया है

Stream.of(names).indexed()
      .filter(e -> e.value().length() <= e.index())
      .map(Indexed::value).toList();

प्रकटीकरण il मैं AbacusUtil का डेवलपर हूं।


1

आप IntStream.iterate()सूचकांक प्राप्त करने के लिए उपयोग कर सकते हैं :

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
List<String> nameList = IntStream.iterate(0, i -> i < names.length, i -> i + 1)
        .filter(i -> names[i].length() <= i)
        .mapToObj(i -> names[i])
        .collect(Collectors.toList());

यह केवल जावा 8 के लिए जावा 8 में काम करता है। आप इसका उपयोग कर सकते हैं:

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
List<String> nameList = IntStream.iterate(0, i -> i + 1)
        .limit(names.length)
        .filter(i -> names[i].length() <= i)
        .mapToObj(i -> names[i])
        .collect(Collectors.toList());

0

अनुक्रमणिका को एनकैप्सुलेट करने के लिए आप एक स्टैटिक इनर क्लास बना सकते हैं जैसा कि मुझे नीचे उदाहरण में करने की आवश्यकता है:

static class Indexer {
    int i = 0;
}

public static String getRegex() {
    EnumSet<MeasureUnit> range = EnumSet.allOf(MeasureUnit.class);
    StringBuilder sb = new StringBuilder();
    Indexer indexer = new Indexer();
    range.stream().forEach(
            measureUnit -> {
                sb.append(measureUnit.acronym);
                if (indexer.i < range.size() - 1)
                    sb.append("|");

                indexer.i++;
            }
    );
    return sb.toString();
}

0

यह प्रश्न ( प्रथम तत्व मिलान बूलियन का सूचकांक प्राप्त करने का स्ट्रीम तरीका ) ने वर्तमान प्रश्न को एक डुप्लिकेट के रूप में चिह्नित किया है, इसलिए मैं वहां इसका जवाब नहीं दे सकता हूं; मैं इसका जवाब यहां दे रहा हूं।

यहां मेलिंग इंडेक्स प्राप्त करने के लिए एक सामान्य समाधान है जिसमें बाहरी पुस्तकालय की आवश्यकता नहीं है।

यदि आपके पास एक सूची है।

public static <T> int indexOf(List<T> items, Predicate<T> matches) {
        return IntStream.range(0, items.size())
                .filter(index -> matches.test(items.get(index)))
                .findFirst().orElse(-1);
}

और इसे इस तरह से कॉल करें:

int index = indexOf(myList, item->item.getId()==100);

और अगर एक संग्रह का उपयोग कर, यह एक प्रयास करें।

   public static <T> int indexOf(Collection<T> items, Predicate<T> matches) {
        int index = -1;
        Iterator<T> it = items.iterator();
        while (it.hasNext()) {
            index++;
            if (matches.test(it.next())) {
                return index;
            }
        }
        return -1;
    }

0

एक संभव तरीका प्रवाह पर प्रत्येक तत्व को अनुक्रमित करना है:

AtomicInteger index = new AtomicInteger();
Stream.of(names)
  .map(e->new Object() { String n=e; public i=index.getAndIncrement(); })
  .filter(o->o.n.length()<=o.i) // or do whatever you want with pairs...
  .forEach(o->System.out.println("idx:"+o.i+" nam:"+o.n));

एक स्ट्रीम के साथ एक अनाम वर्ग का उपयोग करना बहुत उपयोगी नहीं है, जबकि बहुत उपयोगी है।


0

आपको map आवश्यक नहीं है
कि LINQ उदाहरण के लिए निकटतम लैम्ब्डा हो:

int[] idx = new int[] { 0 };
Stream.of( names ).filter( name -> name.length() <= idx[0]++ ).collect( Collectors.toList() );

0
String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
String completeString
         =  IntStream.range(0,namesArray.length)
           .mapToObj(i -> namesArray[i]) // Converting each array element into Object
           .map(String::valueOf) // Converting object to String again
           .collect(Collectors.joining(",")); // getting a Concat String of all values
        System.out.println(completeString);

OUTPUT: सैम, पामेला, डेव, पास्कल, एरिक

String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

IntStream.range(0,namesArray.length)
               .mapToObj(i -> namesArray[i]) // Converting each array element into Object
               .map(String::valueOf) // Converting object to String again
               .forEach(s -> {
                //You can do various operation on each element here
                System.out.println(s);
               }); // getting a Concat String of all 

सूची में एकत्र करने के लिए:

String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
 List<String> namesList
                =  IntStream.range(0,namesArray.length)
                .mapToObj(i -> namesArray[i]) // Converting each array element into Object
                .map(String::valueOf) // Converting object to String again
                .collect(Collectors.toList()); // collecting elements in List
        System.out.println(listWithIndex);

उपरोक्त प्रश्न का हल Listएक तत्व एरिक होने की उम्मीद है ।
कपलान

मैंने सूची में एकत्र करने के लिए एक उदाहरण जोड़ा है।
अर्पण सैनी

0

जैसा कि jean-baptiste-yunès ने कहा, यदि आपकी स्ट्रीम java List पर आधारित है, तो AtomicInteger और उसके incrementAndGet पद्धति का उपयोग करना समस्या का एक बहुत अच्छा समाधान है और लौटा हुआ पूर्णांक मूल सूची में सूचकांक के अनुरूप होता है जब तक कि आप समानांतर धारा का उपयोग न करें।


0

यदि आपको forEach में index की आवश्यकता है तो यह एक तरीका प्रदान करता है।

  public class IndexedValue {

    private final int    index;
    private final Object value;

    public IndexedValue(final int index, final Object value) { 
        this.index = index;
        this.value = value;
    }

    public int getIndex() {
        return index;
    }

    public Object getValue() {
        return value;
    }
}

फिर इसे निम्नानुसार उपयोग करें।

@Test
public void withIndex() {
    final List<String> list = Arrays.asList("a", "b");
    IntStream.range(0, list.size())
             .mapToObj(index -> new IndexedValue(index, list.get(index)))
             .forEach(indexValue -> {
                 System.out.println(String.format("%d, %s",
                                                  indexValue.getIndex(),
                                                  indexValue.getValue().toString()));
             });
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.