জাভা 8 স্ট্রিমগুলিতে, আমি কি এর মধ্যে অবজেক্টগুলিকে সংশোধন / আপডেট করার অনুমতি দেব? যেমন যেমন List<User> users
:
users.stream().forEach(u -> u.setProperty("value"))
জাভা 8 স্ট্রিমগুলিতে, আমি কি এর মধ্যে অবজেক্টগুলিকে সংশোধন / আপডেট করার অনুমতি দেব? যেমন যেমন List<User> users
:
users.stream().forEach(u -> u.setProperty("value"))
উত্তর:
হ্যাঁ, আপনি আপনার স্ট্রিমের অভ্যন্তরের অবজেক্টের স্থিতি পরিবর্তন করতে পারেন তবে বেশিরভাগ ক্ষেত্রে আপনার স্ট্রিমের উত্সের পরিবর্তনকে এড়ানো উচিত । থেকে অ হস্তক্ষেপ প্রবাহ প্যাকেজ ডকুমেন্টেশন আমরা যে পড়তে পারেন বিভাগে:
বেশিরভাগ ডেটা উত্সগুলির জন্য, হস্তক্ষেপ রোধ করা মানে স্ট্রিম পাইপলাইনটি প্রয়োগের সময় ডেটা উত্সটি কোনওভাবেই সংশোধিত হয় না তা নিশ্চিত করা । এর উল্লেখযোগ্য ব্যতিক্রম হ'ল স্ট্রিম যার উত্সগুলি সমবর্তী সংগ্রহ, যা বিশেষত সমবর্তী পরিবর্তনগুলি পরিচালনা করতে ডিজাইন করা হয়েছে। সাম্প্রতিক স্ট্রিম উত্স হ'ল তাদের
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
Iterator
যা পুনরাবৃত্তি করার সময় তালিকার সংশোধন (নতুন উপাদানগুলি সরিয়ে / সংযোজন) প্রতিরোধ করে এবং প্রতিটি স্ট্রিম এবং প্রতিটি লুপ উভয়ই এটি ব্যবহার করছে। আপনি সাধারণ লুপটি ব্যবহার করার চেষ্টা করতে পারেন for(int i=0; ..; ..)
যার মধ্যে এই সমস্যা নেই (তবে অন্য থ্রেড যখন আপনার তালিকাকে সংশোধন করবে তখন আপনাকে থামবে না)। আপনি পছন্দ করতে পদ্ধতি ব্যবহার করতে পারে list.removeAll(Collection)
, list.removeIf(Predicate)
। এছাড়াও java.util.Collections
বর্গ কয়েক পদ্ধতি যা মত উপযোগী হতে পারে addAll(CollectionOfNewElements,list)
।
filter()
কার্যকরী উপায়টি হ'ল:
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]
}
}
এই সমাধানটিতে মূল তালিকাটি সংশোধন করা হয়নি, তবে আপনার প্রত্যাশিত ফলাফলটি একটি নতুন তালিকায় থাকা উচিত যা পুরানোটির মতো একই ভেরিয়েবলের অধীনে অ্যাক্সেসযোগ্য
স্ট্রিমের উত্সে কাঠামোগত পরিবর্তন করা, যেমন পেমেমো তার উত্তরে উল্লেখ করেছেন, একটি সমাধান হ'ল আপনার প্রাথমিক তালিকার অভ্যন্তরীণ আইটেমগুলির Collection
মতো একটি নতুন উদাহরণ তৈরি করা ArrayList
; নতুন তালিকার উপরে পুনরাবৃত্তি করুন এবং প্রাথমিক তালিকায় অপারেশন করুন।
new ArrayList<>(users).stream().forEach(u -> users.remove(u));
সমসাময়িক মোডফিকেশনএক্সেপশন থেকে মুক্তি পেতে কপিরাইটঅনরাইটআরলিলিস্ট ব্যবহার করুন
List<Something>
- আপনার যদি কোনও কপিরাইটঅনরাইটআরলিস্ট হয় তবে কোনও ধারণা নেই। সুতরাং এটি আরও একটি সাধারণ মন্তব্য মত, কিন্তু একটি সত্য উত্তর না।
অদ্ভুত জিনিস তৈরির পরিবর্তে, আপনি ঠিক filter()
এবং তারপরে map()
আপনার ফলাফলটি করতে পারেন ।
এটি অনেক বেশি পাঠযোগ্য এবং নিশ্চিত sure স্ট্রিমগুলি এটি কেবল একটি লুপে তৈরি করবে।
removeIf
শর্তসাপেক্ষে একটি তালিকা থেকে ডেটা অপসারণ করতে আপনি এর ব্যবহার করতে পারেন ।
উদাহরণস্বরূপ: - আপনি যদি একটি তালিকা থেকে সমস্ত সমান সংখ্যা মুছে ফেলতে চান তবে আপনি নীচের হিসাবে এটি করতে পারেন।
final List<Integer> list = IntStream.range(1,100).boxed().collect(Collectors.toList());
list.removeIf(number -> number % 2 == 0);
হ্যাঁ, আপনি একইভাবে তালিকায় থাকা বস্তুর মানগুলিকেও সংশোধন বা আপডেট করতে পারেন:
users.stream().forEach(u -> u.setProperty("some_value"))
তবে উপরের বিবৃতিটি উত্স অবজেক্টগুলিতে আপডেট করবে। যা বেশিরভাগ ক্ষেত্রে গ্রহণযোগ্য নাও হতে পারে।
ভাগ্যক্রমে, আমাদের মতো আরও একটি উপায় রয়েছে:
List<Users> updatedUsers = users.stream().map(u -> u.setProperty("some_value")).collect(Collectors.toList());
যা পুরানোটিকে বাধা না দিয়ে আপডেট তালিকা ফিরিয়ে দেয়।
যেমনটি আগে উল্লেখ করা হয়েছিল - আপনি মূল তালিকাটি সংশোধন করতে পারবেন না তবে আপনি আইটেমটি নতুন তালিকায় স্ট্রিম, সংশোধন এবং সংগ্রহ করতে পারবেন। স্ট্রিং উপাদানকে কীভাবে পরিবর্তন করতে হবে তার সহজ উদাহরণ এখানে।
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]
}
}
এটি কিছুটা দেরি হতে পারে। তবে এখানে ব্যবহারের একটি। এটি ফাইল সংখ্যা গণনা পেতে।
স্মৃতিতে একটি পয়েন্টার তৈরি করুন (এক্ষেত্রে একটি নতুন আপত্তি) এবং অবজেক্টটির সম্পত্তি পরিবর্তন করা আছে। জাভা 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 + "]";
}
}