পুনরাবৃত্তির সময় জাভা 8-এ স্ট্রিমের মধ্যে অবজেক্টগুলি সংশোধন করা হচ্ছে


88

জাভা 8 স্ট্রিমগুলিতে, আমি কি এর মধ্যে অবজেক্টগুলিকে সংশোধন / আপডেট করার অনুমতি দেব? যেমন যেমন List<User> users:

users.stream().forEach(u -> u.setProperty("value"))

উত্তর:


102

হ্যাঁ, আপনি আপনার স্ট্রিমের অভ্যন্তরের অবজেক্টের স্থিতি পরিবর্তন করতে পারেন তবে বেশিরভাগ ক্ষেত্রে আপনার স্ট্রিমের উত্সের পরিবর্তনকে এড়ানো উচিত । থেকে অ হস্তক্ষেপ প্রবাহ প্যাকেজ ডকুমেন্টেশন আমরা যে পড়তে পারেন বিভাগে:

বেশিরভাগ ডেটা উত্সগুলির জন্য, হস্তক্ষেপ রোধ করা মানে স্ট্রিম পাইপলাইনটি প্রয়োগের সময় ডেটা উত্সটি কোনওভাবেই সংশোধিত হয় না তা নিশ্চিত করা । এর উল্লেখযোগ্য ব্যতিক্রম হ'ল স্ট্রিম যার উত্সগুলি সমবর্তী সংগ্রহ, যা বিশেষত সমবর্তী পরিবর্তনগুলি পরিচালনা করতে ডিজাইন করা হয়েছে। সাম্প্রতিক স্ট্রিম উত্স হ'ল তাদের Spliteratorপ্রতিবেদনের CONCURRENTবৈশিষ্ট্য।

সুতরাং এটি ঠিক আছে

  List<User> users = getUsers();
  users.stream().forEach(u -> u.setProperty(value));
//                       ^    ^^^^^^^^^^^^^

তবে বেশিরভাগ ক্ষেত্রে এটি হয় না

  users.stream().forEach(u -> users.remove(u));
//^^^^^                       ^^^^^^^^^^^^

এবং ConcurrentModificationExceptionএনপিইর মতো অপ্রত্যাশিত ব্যতিক্রম ছোঁড়া বা এমনকি হতে পারে :

List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());

list.stream()
    .filter(i -> i > 5)
    .forEach(i -> list.remove(i));  //throws NullPointerException

4
আপনি যদি ব্যবহারকারীদের পরিবর্তন করতে চান তবে সমাধানগুলি কী কী?
অগাস্টাস

4
@ অগাস্টাস এই সমস্ত কিছুর উপর নির্ভর করে আপনি কীভাবে এই তালিকাটি পরিবর্তন করতে চান। তবে সাধারণত আপনার এড়াতে হবে Iteratorযা পুনরাবৃত্তি করার সময় তালিকার সংশোধন (নতুন উপাদানগুলি সরিয়ে / সংযোজন) প্রতিরোধ করে এবং প্রতিটি স্ট্রিম এবং প্রতিটি লুপ উভয়ই এটি ব্যবহার করছে। আপনি সাধারণ লুপটি ব্যবহার করার চেষ্টা করতে পারেন for(int i=0; ..; ..)যার মধ্যে এই সমস্যা নেই (তবে অন্য থ্রেড যখন আপনার তালিকাকে সংশোধন করবে তখন আপনাকে থামবে না)। আপনি পছন্দ করতে পদ্ধতি ব্যবহার করতে পারে list.removeAll(Collection), list.removeIf(Predicate)। এছাড়াও java.util.Collectionsবর্গ কয়েক পদ্ধতি যা মত উপযোগী হতে পারে addAll(CollectionOfNewElements,list)
প্লেমো

@ শেমো, এর একটি সমাধান আপনার প্রাথমিক তালিকার ভিতরে থাকা আইটেমগুলি সহ অ্যারেলিস্টের মতো সংগ্রহের একটি নতুন উদাহরণ তৈরি করা; নতুন তালিকার উপরে পুনরাবৃত্তি করুন এবং প্রাথমিক তালিকায় অপারেশন করুন: নতুন অ্যারেলিস্ট <> (ব্যবহারকারী) .stream.forEach (u -> users.remove (u));
এমএনজেড

4
@ ব্লাউহির্ন কী সমাধান করবেন? স্ট্রিম ব্যবহার করার সময় আমাদের স্ট্রিমের উত্স পরিবর্তন করতে দেওয়া হয় না তবে এর উপাদানগুলির স্থিতি সংশোধন করার অনুমতি দেওয়া হয়। আমরা মানচিত্র, ভবিষ্যদ্বাণী বা অন্যান্য স্ট্রিম পদ্ধতি ব্যবহার করি তা বিবেচনা করে না।
Pshemo

4
সংগ্রহটি পরিবর্তনের পরিবর্তে আমি ব্যবহারের পরামর্শ দেবfilter()
jontro

5

কার্যকরী উপায়টি হ'ল:

import static java.util.stream.Collectors.toList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class PredicateTestRun {

    public static void main(String[] args) {

        List<String> lines = Arrays.asList("a", "b", "c");
        System.out.println(lines); // [a, b, c]
        Predicate<? super String> predicate = value -> "b".equals(value);
        lines = lines.stream().filter(predicate.negate()).collect(toList());

        System.out.println(lines); // [a, c]
    }
}

এই সমাধানটিতে মূল তালিকাটি সংশোধন করা হয়নি, তবে আপনার প্রত্যাশিত ফলাফলটি একটি নতুন তালিকায় থাকা উচিত যা পুরানোটির মতো একই ভেরিয়েবলের অধীনে অ্যাক্সেসযোগ্য


3

স্ট্রিমের উত্সে কাঠামোগত পরিবর্তন করা, যেমন পেমেমো তার উত্তরে উল্লেখ করেছেন, একটি সমাধান হ'ল আপনার প্রাথমিক তালিকার অভ্যন্তরীণ আইটেমগুলির Collectionমতো একটি নতুন উদাহরণ তৈরি করা ArrayList; নতুন তালিকার উপরে পুনরাবৃত্তি করুন এবং প্রাথমিক তালিকায় অপারেশন করুন।

new ArrayList<>(users).stream().forEach(u -> users.remove(u));

1

সমসাময়িক মোডফিকেশনএক্সেপশন থেকে মুক্তি পেতে কপিরাইটঅনরাইটআরলিলিস্ট ব্যবহার করুন


4
এটি আসলে সঠিক, তবে: এটি এখানে ব্যবহৃত নির্দিষ্ট শ্রেণীর উপর নির্ভর করে। তবে যখন আপনি কেবল জানেন যে আপনার একটি রয়েছে List<Something>- আপনার যদি কোনও কপিরাইটঅনরাইটআরলিস্ট হয় তবে কোনও ধারণা নেই। সুতরাং এটি আরও একটি সাধারণ মন্তব্য মত, কিন্তু একটি সত্য উত্তর না।
ঘোস্টট্যাগ

যদি তিনি এটিকে মন্তব্য হিসাবে পোস্ট করেন তবে সম্ভবত কেউ তাকে বলে যে তাঁর মন্তব্য হিসাবে উত্তর পোস্ট করা উচিত নয়।
বিল কে

1

অদ্ভুত জিনিস তৈরির পরিবর্তে, আপনি ঠিক filter()এবং তারপরে map()আপনার ফলাফলটি করতে পারেন ।

এটি অনেক বেশি পাঠযোগ্য এবং নিশ্চিত sure স্ট্রিমগুলি এটি কেবল একটি লুপে তৈরি করবে।


1

removeIfশর্তসাপেক্ষে একটি তালিকা থেকে ডেটা অপসারণ করতে আপনি এর ব্যবহার করতে পারেন ।

উদাহরণস্বরূপ: - আপনি যদি একটি তালিকা থেকে সমস্ত সমান সংখ্যা মুছে ফেলতে চান তবে আপনি নীচের হিসাবে এটি করতে পারেন।

    final List<Integer> list = IntStream.range(1,100).boxed().collect(Collectors.toList());

    list.removeIf(number -> number % 2 == 0);

1

হ্যাঁ, আপনি একইভাবে তালিকায় থাকা বস্তুর মানগুলিকেও সংশোধন বা আপডেট করতে পারেন:

users.stream().forEach(u -> u.setProperty("some_value"))

তবে উপরের বিবৃতিটি উত্স অবজেক্টগুলিতে আপডেট করবে। যা বেশিরভাগ ক্ষেত্রে গ্রহণযোগ্য নাও হতে পারে।

ভাগ্যক্রমে, আমাদের মতো আরও একটি উপায় রয়েছে:

List<Users> updatedUsers = users.stream().map(u -> u.setProperty("some_value")).collect(Collectors.toList());

যা পুরানোটিকে বাধা না দিয়ে আপডেট তালিকা ফিরিয়ে দেয়।


0

যেমনটি আগে উল্লেখ করা হয়েছিল - আপনি মূল তালিকাটি সংশোধন করতে পারবেন না তবে আপনি আইটেমটি নতুন তালিকায় স্ট্রিম, সংশোধন এবং সংগ্রহ করতে পারবেন। স্ট্রিং উপাদানকে কীভাবে পরিবর্তন করতে হবে তার সহজ উদাহরণ এখানে।

public class StreamTest {

    @Test
    public void replaceInsideStream()  {
        List<String> list = Arrays.asList("test1", "test2_attr", "test3");
        List<String> output = list.stream().map(value -> value.replace("_attr", "")).collect(Collectors.toList());
        System.out.println("Output: " + output); // Output: [test1, test2, test3]
    }
}

-1

এটি কিছুটা দেরি হতে পারে। তবে এখানে ব্যবহারের একটি। এটি ফাইল সংখ্যা গণনা পেতে।

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

Path path = Paths.get("/Users/XXXX/static/test.txt");



Count c = new Count();
            c.setCount(0);
            Files.lines(path).forEach(item -> {
                c.setCount(c.getCount()+1);
                System.out.println(item);});
            System.out.println("line count,"+c);

public static class Count{
        private int count;

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }

        @Override
        public String toString() {
            return "Count [count=" + count + "]";
        }



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