জাভা 8 স্ট্রিম - বনাম হ্রাস সংগ্রহ করুন


143

আপনি কখন collect()বনাম ব্যবহার করবেন reduce()? কারও কাছে কী একরকম বা অন্য পথে যাওয়ার পক্ষে আরও ভাল, এর উদাহরণ রয়েছে?

জাভাডোক উল্লেখ করেছেন যে সংগ্রহ () সংগ্রহ একটি পরিবর্তনীয় হ্রাস

এটি একটি পরিবর্তনীয় হ্রাস হ্রাস হিসাবে, আমি ধরে নিই এর জন্য সিঙ্ক্রোনাইজেশন (অভ্যন্তরীণ) প্রয়োজন যা ফলস্বরূপ, কার্য সম্পাদনের জন্য ক্ষতিকারক হতে পারে। reduce()কমানোর প্রতিটি পদক্ষেপের পরে ফেরতের জন্য একটি নতুন ডেটা কাঠামো তৈরি করার ব্যয়ে সম্ভবত আরও তাত্ক্ষণিকভাবে সমান্তরাল।

উপরের বিবৃতিগুলি অনুমানের কাজ তবে আমি এখানে চিমটি দেওয়ার জন্য একটি বিশেষজ্ঞকে পছন্দ করব।


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

1
অ্যাঞ্জেলিকা ল্যাঙ্গার দ্বারা "জাভা 8-এ স্ট্রিমগুলি: হ্রাস বনাম সংগ্রহ সংগ্রহ করুন" দেখুন - youtube.com/watch?v=oWlWEKNM5Aw
মাস্টারজয়ে 2

উত্তর:


115

reduceএটি " ভাঁজ " অপারেশন, এটি স্ট্রিমের প্রতিটি উপাদানগুলিতে একটি বাইনারি অপারেটর প্রয়োগ করে যেখানে অপারেটরের কাছে প্রথম যুক্তি হ'ল পূর্ববর্তী অ্যাপ্লিকেশনটির রিটার্ন মান এবং দ্বিতীয় যুক্তি হ'ল বর্তমান প্রবাহ উপাদান।

collectএকত্রিতকরণ অপারেশন যেখানে একটি "সংগ্রহ" তৈরি করা হয় এবং প্রতিটি উপাদান সেই সংগ্রহে "যুক্ত" হয়। স্ট্রিমের বিভিন্ন অংশে সংগ্রহগুলি তখন একসাথে যুক্ত করা হয়।

আপনি যে দস্তাবেজটি সংযুক্ত দুটি ভিন্ন পন্থা থাকার কারণটা দেয়:

যদি আমরা স্ট্রিংগুলির একটি স্ট্রিম নিতে এবং সেগুলিকে একটি দীর্ঘ দীর্ঘ স্ট্রিংয়ের সাথে যুক্ত করতে চাইতাম, তবে আমরা সাধারণ হ্রাস সহ এটি অর্জন করতে পারি:

 String concatenated = strings.reduce("", String::concat)  

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

সুতরাং মুল বক্তব্যটি হল যে উভয় ক্ষেত্রেই সমান্তরালতা একই রকম তবে reduceক্ষেত্রে আমরা ফাংশনটি স্ট্রিমের উপাদানগুলিতে নিজেরাই প্রয়োগ করি। ইন collectকেস আমরা একটি চপল ধারক ফাংশন প্রয়োগ করুন।


1
যদি সংগ্রহের ক্ষেত্রে এটি হয়: "আরও একটি পারফরম্যান্ট পদ্ধতির ফলাফলগুলি স্ট্রিংবিল্ডারে জমা করা" তখন আমরা কেন কখনও হ্রাস ব্যবহার করব?
jimhooker2002

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

1
@ পণ্য উদাহরণে jimhooker2002, intহয় অপরিবর্তনীয় যাতে আপনি সহজেই একটি সংগ্রহ অপারেশন ব্যবহার করতে পারবেন না। আপনি একটি নোংরা হ্যাক যেমন AtomicIntegerকিছু ব্যবহার করতে পারেন বা কিছু কাস্টম ব্যবহার IntWrapperকরতে পারেন তবে আপনি কেন করবেন? একটি ভাঁজ অপারেশন সংগ্রহ সংগ্রহের সাথে কেবল আলাদা different
বরিস স্পাইডার

17
এছাড়াও অন্য একটি reduceপদ্ধতি রয়েছে, যেখানে আপনি প্রবাহের উপাদানগুলির চেয়ে পৃথক ধরণের জিনিসগুলি ফিরে আসতে পারেন।
দামালুয়ার

1
আপনি হ্রাসের পরিবর্তে সংগ্রহটি ব্যবহার করবেন এমন আরও একটি ক্ষেত্রে হ'ল যখন হ্রাস অপারেশনে কোনও সংকলনে উপাদান যুক্ত করা জড়িত থাকে, তারপরে যতবার আপনার সংযোজক ফাংশন কোনও উপাদানকে প্রক্রিয়া করে, তখন এটি একটি নতুন সংগ্রহ তৈরি করে যা উপাদানটি অন্তর্ভুক্ত করে, যা অদক্ষ is
রঘু

40

কারণটি কেবল এটি:

  • collect() শুধুমাত্র কাজ করতে পারেন পরিবর্তনীয় ফলাফল অবজেক্টের সাথে পারে।
  • reduce()কাজ করার জন্য ডিজাইন করা হয়েছেঅপরিবর্তনীয় ফলাফল অবজেক্টের সাথে ।

"reduce() অপরিবর্তনীয়" উদাহরণ সহ

public class Employee {
  private Integer salary;
  public Employee(String aSalary){
    this.salary = new Integer(aSalary);
  }
  public Integer getSalary(){
    return this.salary;
  }
}

@Test
public void testReduceWithImmutable(){
  List<Employee> list = new LinkedList<>();
  list.add(new Employee("1"));
  list.add(new Employee("2"));
  list.add(new Employee("3"));

  Integer sum = list
  .stream()
  .map(Employee::getSalary)
  .reduce(0, (Integer a, Integer b) -> Integer.sum(a, b));

  assertEquals(Integer.valueOf(6), sum);
}

" collect()পরিবর্তনীয়" উদাহরণ সহ

যেমন আপনি নিজে ব্যবহার করে একটি যোগফল গণনা করতে চাই যদি collect()সঙ্গে এটি কাজ করতে পারছে না BigDecimalকিন্তু শুধুমাত্র সঙ্গে MutableIntথেকেorg.apache.commons.lang.mutable উদাহরণস্বরূপ। দেখা:

public class Employee {
  private MutableInt salary;
  public Employee(String aSalary){
    this.salary = new MutableInt(aSalary);
  }
  public MutableInt getSalary(){
    return this.salary;
  }
}

@Test
public void testCollectWithMutable(){
  List<Employee> list = new LinkedList<>();
  list.add(new Employee("1"));
  list.add(new Employee("2"));

  MutableInt sum = list.stream().collect(
    MutableInt::new, 
    (MutableInt container, Employee employee) -> 
      container.add(employee.getSalary().intValue())
    , 
    MutableInt::add);
  assertEquals(new MutableInt(3), sum);
}

এটি কাজ করে কারণ সংগ্রহকারীর container.add(employee.getSalary().intValue()); ফলাফলের সাথে কোনও নতুন অবজেক্ট ফেরত দেওয়ার কথা নয় তবে পরিবর্তকের অবস্থার পরিবর্তন করার কথাcontainer টাইপ MutableInt

আপনি যদি BigDecimalপরিবর্তে এটি ব্যবহার করতে চান তবে containerআপনি collect()পদ্ধতিটি ব্যবহার container.add(employee.getSalary());করতে পারবেন না containerকারণ BigDecimalএটি পরিবর্তনযোগ্য নয় কারণ এটি পরিবর্তনযোগ্য । (এগুলি ছাড়া কোনও খালি নির্মাণকারীর BigDecimal::newকাজ না করে BigDecimal)


2
নোট করুন যে আপনি কোনও Integerকনস্ট্রাক্টর ( new Integer(6)) ব্যবহার করছেন যা পরবর্তী জাভা সংস্করণগুলিতে অবচয় রয়েছে।
এমসি সম্রাট

1
এমসিইসি সম্রাটকে ভাল ধরা! আমি এটিকে পরিবর্তন করেছিInteger.valueOf(6)
স্যান্ড্রো

@ স্যান্ড্রো - আমি বিভ্রান্ত আপনি কেন বলছেন যে সংগ্রহ () কেবলমাত্র পরিবর্তনযোগ্য বস্তুর সাথে কাজ করে? আমি এটি স্ট্রিংগুলি সংযুক্ত করার জন্য ব্যবহার করেছি। স্ট্রিং অল নেমস = কর্মচারী। প্রবাহ ()। ম্যাপ (কর্মচারী :: getNameString) .কলেক্ট করুন (সংগ্রাহক। জোইনিং (",")) .তো স্ট্রিং ();
মাস্টারজয়ে 2

1
@ মাস্টারজো 2 এটি সহজ। সংক্ষেপে - বাস্তবায়ন এখনও StringBuilderপরিবর্তনীয় যা ব্যবহার করে । দেখুন: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/…
সান্দ্রো

30

সাধারণ হ্রাস বলতে দুটি অবারিত মান যেমন আন্ত, ডাবল ইত্যাদি একত্রিত করে একটি নতুন উত্পাদন করা বোঝায় ; এটি একটি অপরিবর্তনীয় হ্রাস। বিপরীতে, সংগ্রহের পদ্ধতিটি এমন একটি ফলাফল সংগ্রহ করার জন্য ধারককে রূপান্তরিত করার জন্য ডিজাইন করা হয়েছিল যাতে ফল উত্পন্ন হওয়ার কথা।

সমস্যাটি চিত্রিত করার জন্য, ধরুন আপনি Collectors.toList()যেমন একটি সাধারণ হ্রাস ব্যবহার করে অর্জন করতে চান

List<Integer> numbers = stream.reduce(
        new ArrayList<Integer>(),
        (List<Integer> l, Integer e) -> {
            l.add(e);
            return l;
        },
        (List<Integer> l1, List<Integer> l2) -> {
            l1.addAll(l2);
            return l1;
        });

এটি এর সমতুল্য Collectors.toList()। যাইহোক, এই ক্ষেত্রে আপনি পরিবর্তন List<Integer>। যেহেতু আমরা জানি যে ArrayListথ্রেড-নিরাপদ নয়, পুনরাবৃত্তির সময় এটি থেকে মানগুলি যুক্ত / অপসারণ করাও নিরাপদ নয় যাতে আপনি হয় সাম্প্রতিক ব্যতিক্রম পাবেন বাArrayIndexOutOfBoundsException তালিকাটি আপডেট করার সাথে সংযোগকারী বা কোনও ধরণের ব্যতিক্রম (বিশেষত সমান্তরালে চালিত হলে) পাবেন you তালিকাগুলি মার্জ করার চেষ্টা করে কারণ আপনি এটিতে পূর্ণসংখ্যা সংগ্রহ করে (যোগ করে) তালিকার পরিবর্তন করছেন। আপনি যদি এই থ্রেড-নিরাপদ করতে চান আপনাকে প্রতিবার একটি নতুন তালিকা পাস করতে হবে যা কার্য সম্পাদনকে ক্ষতিগ্রস্থ করবে।

বিপরীতে, Collectors.toList()একই ধরণের কাজ করে। তবে আপনি তালিকায় মানগুলি সংগ্রহ করার সময় এটি থ্রেড সুরক্ষার গ্যারান্টি দেয়। পদ্ধতির জন্য ডকুমেন্টেশনcollect থেকে :

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

সুতরাং আপনার প্রশ্নের উত্তর দিতে:

আপনি কখন collect()বনাম ব্যবহার করবেন reduce()?

যদি আপনি যেমন অপরিবর্তনীয় মান ints, doubles, Stringsতারপর স্বাভাবিক হ্রাস মাত্র কাজ করে জরিমানা। যাইহোক, যদি reduceআপনার মানগুলি List(পরিবর্তনীয় ডেটা কাঠামো) বলতে হয় তবে আপনাকে collectপদ্ধতির সাথে পরিবর্তনীয় হ্রাস ব্যবহার করতে হবে ।


কোড স্নিপেটে আমি মনে করি সমস্যাটি হ'ল এটি পরিচয়টি গ্রহণ করবে (এক্ষেত্রে একটি অ্যারেলিস্টের একক উদাহরণ) এবং ধরে নেবে এটি "অপরিবর্তনীয়" যাতে তারা xথ্রেড শুরু করতে পারে , প্রতিটি "পরিচয় যুক্ত করে" তারপরে একত্রিত করে। ভালো উদাহরণ.
রজারডপ্যাক ২৩ শে

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

public static void main(String[] args) { List<Integer> l = new ArrayList<>(); l.add(1); l.add(10); l.add(3); l.add(-3); l.add(-4); List<Integer> numbers = l.stream().reduce( new ArrayList<Integer>(), (List<Integer> l2, Integer e) -> { l2.add(e); return l2; }, (List<Integer> l1, List<Integer> l2) -> { l1.addAll(l2); return l1; });for(Integer i:numbers)System.out.println(i); } }আমি চেষ্টা এবং Didnt পেতে CCM ব্যতিক্রম
অমরনাথ হরিশ

আপনারা সমান্তরালভাবে চালানোর চেষ্টা করার সময় এবং অমরনাথারিশ সমস্যাটি দেখা দেয় এবং একাধিক থ্রেড একই তালিকাটি অ্যাক্সেস করার চেষ্টা করে
জর্জে

11

স্ট্রিমটি একটি <- b <- c <- d হতে দিন

হ্রাস,

আপনার ((একটি # খ) # গ) # ডি থাকবে

যেখানে # এটি করা আকর্ষণীয় অপারেশন।

সংগ্রহে,

আপনার সংগ্রাহকের কিছু ধরণের সংগ্রহ কাঠামো থাকবে।

কে গ্রাস করে a। কে তখন খ খ। কে তখন গ। কে তখন খায়।

শেষে, আপনি কে কে জিজ্ঞাসা করলেন চূড়ান্ত ফলাফল কী।

কে তখন এটি আপনাকে দেয়।


2

রানটাইমের সময় এগুলি সম্ভাব্য মেমরির পদচিহ্নগুলির মধ্যে খুব আলাদা। যদিও collect()সংগ্রহ এবং রাখে সব সংগ্রহে মধ্যে ডেটা, reduce()আপনাকে তা নির্দিষ্ট করার স্পষ্টভাবে জিজ্ঞেস এটির সাথে সম্পর্কিত ডেটা প্রবাহ মাধ্যমে করা কমাতে কিভাবে।

উদাহরণস্বরূপ, আপনি যদি কোনও ফাইল থেকে কিছু তথ্য পড়তে চান, এটি প্রক্রিয়া করতে পারেন এবং এটি কোনও ডাটাবেসে রেখে দেন তবে জাভা স্ট্রিম কোডটি এর সমান হতে পারে:

streamDataFromFile(file)
            .map(data -> processData(data))
            .map(result -> database.save(result))
            .collect(Collectors.toList());

এই ক্ষেত্রে, আমরা collect()জাভাটিকে ডেটা স্ট্রিম করতে এবং এটি ডাটাবেসে ফলাফল সংরক্ষণ করতে জোর করে ব্যবহার করি । collect()ডেটা ছাড়া কখনও পড়া হয় না এবং কখনও সংরক্ষণ করা হয় না।

এই কোডটি আনন্দের সাথে java.lang.OutOfMemoryError: Java heap spaceরানটাইম ত্রুটি তৈরি করে , যদি ফাইলের আকার যথেষ্ট বড় হয় বা গাদা আকার যথেষ্ট পরিমাণে কম থাকে। এর সুস্পষ্ট কারণটি হ'ল এটি স্ট্রিমের মাধ্যমে তৈরি হওয়া সমস্ত ডেটা সঞ্চারিত করার চেষ্টা করে (এবং বাস্তবে এটি ইতিমধ্যে ডাটাবেসে সংরক্ষণ করা হয়েছে) ফলাফল সংগ্রহের মধ্যে এবং এই স্তূপটি উড়ে যায়।

তবে, আপনি যদি এর collect()সাথে প্রতিস্থাপন করেন reduce()- এটি আর কোনও সমস্যা হবে না কারণ পরেরগুলি এটির মাধ্যমে তৈরি সমস্ত ডেটা হ্রাস এবং বাতিল করে দেবে।

উপস্থাপিত উদাহরণে কেবল collect()কিছু দিয়ে প্রতিস্থাপন করুন reduce:

.reduce(0L, (aLong, result) -> aLong, (aLong1, aLong2) -> aLong1);

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


3
আপনি যদি আপনার ডিবি সংরক্ষণের ফলাফলগুলি সম্পর্কে চিন্তা না করেন তবে আপনার জন্য প্রতিটি ব্যবহার করা উচিত ... আপনার হ্রাস ব্যবহারের দরকার নেই। যদি না এটি চিত্রণমূলক উদ্দেশ্যে ছিল।
ডেভএডেলস্টাইন

2

এখানে কোড উদাহরণ

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = list.stream().reduce((x,y) -> {
        System.out.println(String.format("x=%d,y=%d",x,y));
        return (x + y);
    }).get();

System.out.println (সমষ্টি);

এখানে কার্যকর করা ফলাফল:

x=1,y=2
x=3,y=3
x=6,y=4
x=10,y=5
x=15,y=6
x=21,y=7
28

ফাংশন হ্যান্ডেল দুটি পরামিতি হ্রাস করুন, প্রথম প্যারামিটারটি পূর্বের রিটার্ন মানটি স্ট্রিমটি হয়, দ্বিতীয় প্যারামিটারটি স্রোতে বর্তমান গণনা মান হয়, এটি পরবর্তী মানকে প্রথম মান হিসাবে প্রথম মান এবং বর্তমান মান যোগ করে sum


0

ডক্স অনুসারে

হ্রাসকারী () সংগ্রহকারীরা মাল্টি-লেভেল হ্রাস, গ্রুপিংবি বা পার্টিশনিংয়ের মাধ্যমে ডাউনস্ট্রিম ব্যবহার করার সময় সবচেয়ে বেশি কার্যকর। একটি স্ট্রিমে একটি সাধারণ হ্রাস করতে, পরিবর্তে স্ট্রিম.রেডস (বাইনারিওপ্রেটার) ব্যবহার করুন।

সুতরাং মূলত আপনি reducing()কেবল যখন কোনও সংগ্রহের মধ্যে জোর করে তখন ব্যবহার করেন । এখানে অন্য একটি উদাহরণ :

 For example, given a stream of Person, to calculate the longest last name 
 of residents in each city:

    Comparator<String> byLength = Comparator.comparing(String::length);
    Map<String, String> longestLastNameByCity
        = personList.stream().collect(groupingBy(Person::getCity,
            reducing("", Person::getLastName, BinaryOperator.maxBy(byLength))));

এই টিউটোরিয়াল অনুযায়ী হ্রাস কখনও কখনও কম দক্ষ হয়

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

সুতরাং পরিচয়টি হ্রাস করার দৃশ্যে "পুনরায় ব্যবহৃত", .reduceযদি সম্ভব হয় তবে আরও কিছুটা দক্ষ ।

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