Java.util.stream. জাভা 8 এ স্ট্রিম থেকে একটি তালিকা পুনরুদ্ধার করা হচ্ছে


443

সংগ্রহগুলি সহজে ফিল্টার করার জন্য আমি জাভা 8 ল্যাম্বডাসের সাথে খেলছিলাম। তবে একই বিবৃতিতে নতুন তালিকা হিসাবে ফলাফলটি পুনরুদ্ধার করার জন্য আমি একটি সংক্ষিপ্ত উপায় খুঁজে পাইনি। এখানে এখন পর্যন্ত আমার সবচেয়ে সংক্ষিপ্ত পন্থা:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);

নেটে উদাহরণগুলি আমার প্রশ্নের উত্তর দেয়নি কারণ তারা একটি নতুন ফলাফলের তালিকা তৈরি না করেই থামছে। আরও একটি সংক্ষিপ্ত উপায় থাকতে হবে। আমি আশা করতাম যে Streamবর্গ পদ্ধতি যেমন হয়েছে toList(), toSet()...

ভেরিয়েবলগুলি targetLongListসরাসরি তৃতীয় লাইনের দ্বারা নির্ধারিত করার কোনও উপায় আছে কি ?


7
সুবিধার্থে আপনার যদি sourceLongListপরে প্রয়োজন হয় না Collection.removeIf(…)
হলগার

2
এ কেমন? List<Long> targetLongList = sourceLongList.stream().collect(Collectors.toList());
leeyuiwah

উত্তর:


609

আপনি যা করছেন তা হ'ল সহজতম উপায়, যদি আপনার স্ট্রিমটি অনুক্রমিক থাকে provided অন্যথায় আপনাকে আগে সিক্যুয়ালিটিতে কল করতে হবে () forEach

[পরবর্তীকালে সম্পাদনা করুন: ক্রমবর্ধমান () এ কল করার কারণটি হ'ল forEach(targetLongList::add)স্ট্রিমটি সমান্তরাল হলে সেই কোডটি যথাযথ হবে। তারপরেও এটি কার্যকর প্রভাব অর্জন করবে না, যেমনটি forEachস্পষ্টভাবে ননডেটরিস্টিনিস্টিক — এমনকি একটি ক্রমিক ধারাতে উপাদান প্রক্রিয়াকরণের ক্রমও নিশ্চিত নয়। forEachOrderedসঠিক ক্রম নিশ্চিত করার জন্য আপনাকে ব্যবহার করতে হবে। স্ট্রিম এপিআই ডিজাইনারদের উদ্দেশ্য হল আপনি নীচে হিসাবে এই পরিস্থিতিতে সংগ্রাহক ব্যবহার করবেন]]

একটি বিকল্প হয়

targetLongList = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(Collectors.toList());

10
সংযোজন: আমি মনে করি যে আপনি যদি কোনও স্ট্যাটিক আমদানি ব্যবহার করেন তবে এই কোডগুলি কিছুটা ছোট, স্বচ্ছ এবং সুন্দর হয়ে উঠবে toList। এই ফাইলটি আমদানি মধ্যে নিম্নলিখিত স্থাপন দ্বারা সম্পন্ন করা হয়: static import java.util.stream.Collectors.toList;। তারপরে সংগ্রহ কলটি কেবল পড়ে .collect(toList())
Lii

4
Eclipse এ IDE পদ্ধতিগুলির জন্য একটি স্ট্যাটিক আমদানি যুক্ত করা সম্ভব। এই যোগ করে সম্পন্ন করা হয় Collectorsমধ্যে বর্গ পছন্দসমূহ -> জাভা -> এডিটর -> সামগ্রী সহায়তা -> প্রিয় । এর পরে, আইডিই পূরণ করতে এবং স্ট্যাটিক আমদানি যুক্ত করতে আপনাকে কেবল toLiহিট সিটিআর + স্পেসে টাইপ করতে হবে toList
Lii

3
মনে রাখতে হবে একটা জিনিষ যে IntStreamএবং কিছু অন্যান্য প্রায় কিন্তু-না quite- Streamগুলি না collect(Collector)পদ্ধতি এবং আপনি কল করতে হবে IntStream.boxed()তাদের একটি নিয়মিত রূপান্তর Streamপ্রথম। তারপরে আবার, সম্ভবত আপনি কেবল চান toArray()
মিউট্যান্ট বব

আমরা ব্যবহার করতে হবে কেন sequential()আগে forEachবা ব্যবহারের 'forEachOrdered`
অমরনাথ হরিশ

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

183

আপডেট করা হয়েছে:

আর একটি পদ্ধতির ব্যবহার হ'ল Collectors.toList:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toList());

পূর্ববর্তী সমাধান:

আর একটি পদ্ধতির ব্যবহার হ'ল Collectors.toCollection:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toCollection(ArrayList::new));

60
আপনি যদি একটি নির্দিষ্ট তালিকা বাস্তবায়ন চান তবে এটি কার্যকর।
অরবফিশ

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

3
Collectors::toListজাভাডোক থেকে এই পদ্ধতির জন্য আরেকটি সমর্থক : "প্রত্যাবর্তিত তালিকার ধরণ, পরিবর্তনশীলতা, সিরিয়ালাইজিবিলিটি বা থ্রেড-সুরক্ষার কোনও গ্যারান্টি নেই; ফেরত তালিকার উপর আরও নিয়ন্ত্রণের প্রয়োজন হলে ব্যবহার করুন toCollection(Supplier)।"
চার্লস উড

12

আমি এমন একটি ব্যবহারের পদ্ধতি ব্যবহার করতে চাই যা কোনও সংগ্রাহককে ArrayListযখন আমি চাই তা ফেরত দেয় ।

আমি মনে করি যে সমাধানটি ব্যবহার Collectors.toCollection(ArrayList::new)করা এই জাতীয় প্রচলনের জন্য কিছুটা গোলমাল।

উদাহরণ:

ArrayList<Long> result = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(toArrayList());

public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
    return Collectors.toCollection(ArrayList::new);
}

এই উত্তরের সাথে আমি এটিও প্রদর্শন করতে চাই যে কাস্টম সংগ্রহকারী তৈরি এবং ব্যবহার করা কতটা সহজ, যা সাধারণত খুব কার্যকর।


যদি আপনি ফলাফলটিকে তালিকা হিসাবে ঘোষণা করেন <দীর্ঘ> আপনার এই ব্যবহার পদ্ধতিটি ব্যবহার করার দরকার নেই। সংগ্রাহক। টু লিস্ট করবেন। এছাড়াও, ইন্টারফেসের পরিবর্তে নির্দিষ্ট ক্লাস ব্যবহার করা কোডের গন্ধ।
ল্লুইস মার্টিনেজ

1
@ ল্লুইস মার্টিনেজ: "সংগ্রাহক। টোলিস্ট এটি করবে।" : না, অনেক পরিস্থিতিতে নয়। কারণ toListআপনি যদি উদাহরণস্বরূপ প্রোগ্রামে তালিকাটি পরে পরিবর্তন করতে চান তবে এটি ব্যবহার করা ভাল ধারণা নয় । toListডকুমেন্টেশন এই বলে: "টাইপ, পরিবর্তনশীলতা, serializability, অথবা তালিকা থ্রেড-নিরাপত্তা ফিরে কোন গ্যারান্টী আছে, যদি ফিরে তালিকা উপর আরো বেশি নিয়ন্ত্রণ প্রয়োজন বোধ করা হয়, ব্যবহার toCollection।" । আমার উত্তরটি সাধারণ ক্ষেত্রে এটি করা আরও সুবিধাজনক করার উপায় দেখায়।
লি

আপনি যদি বিশেষভাবে একটি অ্যারেলিস্ট তৈরি করতে চান তবে ঠিক আছে।
ল্লুইস মার্টিনেজ

5

আপনার যদি আদিমগুলির একটি অ্যারে থাকে তবে আপনি Eclipse সংগ্রহগুলিতে উপলভ্য আদিম সংগ্রহগুলি ব্যবহার করতে পারেন ।

LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
LongList targetLongList = sourceLongList.select(l -> l > 100);

আপনি যদি উত্স লংলিস্ট থেকে পরিবর্তন করতে না পারেন তবে List:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = 
    ListAdapter.adapt(sourceLongList).select(l -> l > 100, new ArrayList<>());

আপনি যদি ব্যবহার করতে চান LongStream:

long[] sourceLongs = new long[]{1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L};
LongList targetList = 
    LongStream.of(sourceLongs)
    .filter(l -> l > 100)
    .collect(LongArrayList::new, LongArrayList::add, LongArrayList::addAll);

দ্রষ্টব্য: আমি গ্রহন গ্রাহক সংগ্রহের একজন সহযোগী।


4

কিছুটা আরও কার্যকর উপায় (উত্স তালিকা তৈরি করতে এবং ফিল্টার দ্বারা স্ব-আনবক্সিং এড়ানো):

List<Long> targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L)
    .filter(l -> l > 100)
    .boxed()
    .collect(Collectors.toList());


1

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

আপনি কেবল লিখতে পারেন-

ListX<Long> sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
ListX<Long> targetLongList = sourceLongList.filter(l -> l > 100);

লিস্টএক্স একটি বিদ্যমান তালিকা থেকেও তৈরি করা যেতে পারে (ListX.fromIterable এর মাধ্যমে)


1

লংস্ট্রিম ক্লাস এবং একইভাবে ইন্টারস্ট্রিম এবং ডাবল স্ট্রিম ক্লাস দ্বারা সরবরাহিত সংগ্রহ পদ্ধতির আর একটি রূপ রয়েছে।

<R> R collect(Supplier<R> supplier,
              ObjLongConsumer<R> accumulator,
              BiConsumer<R,R> combiner)

এই স্ট্রীমের উপাদানগুলিতে একটি পরিবর্তনীয় হ্রাস অপারেশন সম্পাদন করে। একটি পরিবর্তনীয় হ্রাস হ'ল একটি হ'ল যার মধ্যে হ্রাসকৃত মান হ'ল একটি পরিবর্তনীয় ফলাফল ধারক যেমন একটি অ্যারেলিস্ট এবং ফলাফলগুলি প্রতিস্থাপনের পরিবর্তে উপাদানগুলির ফলাফলের আপডেট করে উপাদানগুলি অন্তর্ভুক্ত করা হয়। এটি এর সমতুল্য একটি ফলাফল উত্পাদন করে:

R result = supplier.get();
  for (long element : this stream)
       accumulator.accept(result, element);
  return result;

হ্রাস করার মতো (দীর্ঘ, লংবাইনারি অপারেটর), সংগ্রহের ক্রিয়াকলাপগুলি অতিরিক্ত সিঙ্ক্রোনাইজেশন না করে সমান্তরাল করা যায়। এটি একটি টার্মিনাল অপারেশন।

এবং এই সংগ্রহ পদ্ধতির সাথে আপনার প্রশ্নের উত্তর নীচের মত:

    LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2)
    .collect(ArrayList::new, (list, value) -> list.add(value)
    , (list1, list2) -> list1.addAll(list2));

নীচে পদ্ধতির রেফারেন্স বৈকল্পিক যা বেশ স্মার্ট তবে কিছু বুঝতে অসুবিধাজনক:

     LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2)
    .collect(ArrayList::new, List::add , List::addAll);

নীচে হ্যাশসেট বৈকল্পিক হবে:

     LongStream.of(1L, 2L, 3L, 3).filter(i -> i > 2)
     .collect(HashSet::new, HashSet::add, HashSet::addAll);

একইভাবে লিংকডলিস্ট বৈকল্পিকটি এরকম:

     LongStream.of(1L, 2L, 3L, 3L)
     .filter(i -> i > 2)
     .collect(LinkedList::new, LinkedList::add, LinkedList::addAll);

0

যদি কেউ (আমার মতো) বাইরে আধ্যাত্মিক প্রকারের পরিবর্তে অবজেক্টের সাথে ব্যবহারের উপায়ের সন্ধান করে mapToObj()

String ss = "An alternative way is to insert the following VM option before "
        + "the -vmargs option in the Eclipse shortcut properties(edit the "
        + "field Target inside the Shortcut tab):";

List<Character> ll = ss
                        .chars()
                        .mapToObj(c -> new Character((char) c))
                        .collect(Collectors.toList());

System.out.println("List type: " + ll.getClass());
System.out.println("Elem type: " + ll.get(0).getClass());
ll.stream().limit(50).forEach(System.out::print);

কপি করে প্রিন্ট:

List type: class java.util.ArrayList
Elem type: class java.lang.Character
An alternative way is to insert the following VM o

0
String joined = 
                Stream.of(isRead?"read":"", isFlagged?"flagged":"", isActionRequired?"action":"", isHide?"hide":"")
                      .filter(s -> s != null && !s.isEmpty())
                      .collect(Collectors.joining(","));

0

AbacusUtil দ্বারা কোড এখানে

LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList();

প্রকাশ : আমি অ্যাবাকাসটিলের বিকাশকারী।


লংস্ট্রিম ক্লাসে উপস্থিত কোনও টোললিস্ট পদ্ধতি আমি পাই না। আপনি এই কোড চালাতে পারেন?
ভনীত কাটারিয়া

@ ভনীটকাটারিয়া চেষ্টা করুন com.landawn.abacus.util.stream.LongStreamবা LongStreamExঅ্যাবাকাসটিল
ব্যবহারকারী 14380739

0

আপনি নীচের মত কোড পুনরায় লিখতে পারেন:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = sourceLongList.stream().filter(l -> l > 100).collect(Collectors.toList());

আপনার ইনপুট জন্য ধন্যবাদ। তবে দয়া করে আপনি কী পরিবর্তন করেছেন এবং এটি প্রশ্নের সাথে কতটা সম্পর্কিত explain
বি - রিয়ান

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

0

পরিবর্তনীয় তালিকায় সংগ্রহ করতে:

targetList = sourceList.stream()
                       .filter(i -> i > 100) //apply filter
                       .collect(Collectors.toList());

অপরিবর্তনীয় তালিকায় সংগ্রহ করতে:

targetList = sourceList.stream()
                       .filter(i -> i > 100) //apply filter
                       .collect(Collectors.toUnmodifiableList());

জাভাডকcollect থেকে ব্যাখ্যা :

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

এটি একটি টার্মিনাল অপারেশন।

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


-3

আপনি যদি এটি ব্যবহার না করেন parallel()তবে কাজ করবে

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);

List<Long> targetLongList =  new ArrayList<Long>();

sourceLongList.stream().peek(i->targetLongList.add(i)).collect(Collectors.toList());

আমি পছন্দ করি না যে সংগ্রহটি () কেবলমাত্র স্ট্রিম চালাতে ব্যবহৃত হয় যাতে প্রতিটি আইটেমটিতে উঁকি দেওয়া () হুক ডাকা হয়। টার্মিনাল অপারেশন ফলাফল বাতিল করা হয়।
ড্যানিয়েল কে।

কল করা খুব অদ্ভুত collectএবং তারপরে রিটার্নের মানটি সংরক্ষণ না করে। সেক্ষেত্রে আপনি forEachপরিবর্তে ব্যবহার করতে পারেন । তবে এটি এখনও একটি দুর্বল সমাধান।
লী

1
এইভাবে পিক () ব্যবহার করা একটি অ্যান্টিপ্যাটার্ন।
গ্রজেগোর্জ পাইওয়োয়ারেক

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