মানক কোটলিন লাইব্রেরিতে জাভা 8 স্ট্রিম.কলেক্ট সমতুল্য কী পাওয়া যায়?


180

জাভা 8-এ, Stream.collectসংগ্রহগুলিতে একত্রিত করার অনুমতি দেয়। কোটলিনে, এটি একই উপায়ে উপস্থিত নেই, সম্ভবত stdlib এর এক্সটেনশন ফাংশনগুলির সংগ্রহ হিসাবে অন্য। তবে এটি স্পষ্ট নয় যে বিভিন্ন ব্যবহারের ক্ষেত্রে সমতা কী।

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

অনলাইন সংস্থানসমূহের ক্ষেত্রে কোটলিন সংগ্রহের উদাহরণ দেখানো, এগুলি সাধারণত নগণ্য এবং সত্যই একই ব্যবহারের ক্ষেত্রে তুলনা করে না। জাভা 8 এর জন্য নথিভুক্তের মতো ঘটনাগুলির সাথে সত্যিই মেলে এমন ভাল উদাহরণগুলি কী কী Stream.collect? সেখানে তালিকা রয়েছে:

  • একটি তালিকাতে নাম একত্রিত করুন
  • একটি ট্রিসেটে নাম একত্রিত করুন
  • উপাদানগুলিকে স্ট্রিংয়ে রূপান্তর করুন এবং কমা দিয়ে আলাদা করুন conc
  • কর্মচারীর বেতনের অঙ্কের পরিমাণ
  • বিভাগ দ্বারা গ্রুপ কর্মীরা
  • বিভাগ দ্বারা বেতনের পরিমাণ গণনা
  • পার্টিশন শিক্ষার্থীরা উত্তীর্ণ এবং ব্যর্থতার মধ্যে পড়ে

উপরে বর্ণিত জাভডোকের বিশদ সহ।

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


ক্ষেত্রে collect(Collectors.toList())বা ব্যবহারের অনুরূপ বা অনুরূপ ছাড়া আপনার আর কোনও উপায় নেই , তবে আপনি এই সমস্যাটি হিট করতে পারেন: stackoverflow.com/a/35722167/3679676 (সমস্যাটি সহ, ইস্যু)
জেইসন মিনার্ড

উত্তর:


256

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

আমি মনে করি অন্তর্নির্মিত জাভা 8 Collectorsশ্রেণির একমাত্র জিনিসটি হ'ল সংক্ষিপ্তকরণ (তবে এই প্রশ্নের অন্য উত্তরে একটি সহজ সমাধান)

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

সম্পাদনা 11.08.2017: কোটলিন 1.2 এম 2 এ অবিচ্ছিন্ন / উইন্ডোযুক্ত সংগ্রহের ক্রিয়াকলাপগুলি যুক্ত করা হয়েছে, দেখুন https://blog.jetbrains.com/kotlin/2017/08/kotlin-1-2-m2-is-out/


ইতিমধ্যে সেখানে উপস্থিত থাকতে পারে এমন নতুন ফাংশন তৈরি করার আগে সামগ্রিকভাবে কোটলিন.কলেকশনগুলির জন্য API রেফারেন্সটি অন্বেষণ করা ভাল always

Stream.collectকোটলিনের সমতুল্য জাভা 8 উদাহরণ থেকে এখানে কিছু রূপান্তর রয়েছে :

একটি তালিকাতে নাম একত্রিত করুন

// Java:  
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
// Kotlin:
val list = people.map { it.name }  // toList() not needed

উপাদানগুলিকে স্ট্রিংয়ে রূপান্তর করুন এবং কমা দিয়ে আলাদা করুন conc

// Java:
String joined = things.stream()
                       .map(Object::toString)
                       .collect(Collectors.joining(", "));
// Kotlin:
val joined = things.joinToString(", ")

কর্মচারীর বেতনের অঙ্কের পরিমাণ

// Java:
int total = employees.stream()
                      .collect(Collectors.summingInt(Employee::getSalary)));
// Kotlin:
val total = employees.sumBy { it.salary }

বিভাগ দ্বারা গ্রুপ কর্মীরা

// Java:
Map<Department, List<Employee>> byDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment));
// Kotlin:
val byDept = employees.groupBy { it.department }

বিভাগ দ্বারা বেতনের পরিমাণ গণনা

// Java:
Map<Department, Integer> totalByDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment,
                     Collectors.summingInt(Employee::getSalary)));
// Kotlin:
val totalByDept = employees.groupBy { it.dept }.mapValues { it.value.sumBy { it.salary }}

পার্টিশন শিক্ষার্থীরা উত্তীর্ণ এবং ব্যর্থতার মধ্যে পড়ে

// Java:
Map<Boolean, List<Student>> passingFailing =
     students.stream()
             .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
// Kotlin:
val passingFailing = students.partition { it.grade >= PASS_THRESHOLD }

পুরুষ সদস্যের নাম

// Java:
List<String> namesOfMaleMembers = roster
    .stream()
    .filter(p -> p.getGender() == Person.Sex.MALE)
    .map(p -> p.getName())
    .collect(Collectors.toList());
// Kotlin:
val namesOfMaleMembers = roster.filter { it.gender == Person.Sex.MALE }.map { it.name }

লিঙ্গ অনুসারে রোস্টার সদস্যদের গ্রুপের নাম

// Java:
Map<Person.Sex, List<String>> namesByGender =
      roster.stream().collect(
        Collectors.groupingBy(
            Person::getGender,                      
            Collectors.mapping(
                Person::getName,
                Collectors.toList())));
// Kotlin:
val namesByGender = roster.groupBy { it.gender }.mapValues { it.value.map { it.name } }   

অন্য তালিকায় একটি তালিকা ফিল্টার করুন

// Java:
List<String> filtered = items.stream()
    .filter( item -> item.startsWith("o") )
    .collect(Collectors.toList());
// Kotlin:
val filtered = items.filter { it.startsWith('o') } 

সংক্ষিপ্ততম স্ট্রিং একটি তালিকা সন্ধান করা

// Java:
String shortest = items.stream()
    .min(Comparator.comparing(item -> item.length()))
    .get();
// Kotlin:
val shortest = items.minBy { it.length }

ফিল্টার প্রয়োগের পরে তালিকায় আইটেম গণনা

// Java:
long count = items.stream().filter( item -> item.startsWith("t")).count();
// Kotlin:
val count = items.filter { it.startsWith('t') }.size
// but better to not filter, but count with a predicate
val count = items.count { it.startsWith('t') }

এবং এটি এখনও চলে ... সমস্ত ক্ষেত্রে, কোনও বিশেষ ভাঁজ, হ্রাস বা অন্য কার্যকারিতা নকল করার প্রয়োজন ছিল না Stream.collect। আপনার যদি আরও ব্যবহারের মামলা থাকে তবে সেগুলিকে মন্তব্যে যুক্ত করুন এবং আমরা দেখতে পারি!

অলসতা সম্পর্কে

আপনি যদি একটি শৃঙ্খলা অলস করতে চান তবে আপনি চেইনের আগে Sequenceব্যবহার করে রূপান্তর করতে পারেন asSequence()। ক্রিয়াকলাপগুলির শৃঙ্খলা শেষে, আপনি সাধারণত Sequenceপাশাপাশি শেষ করেন । তারপর আপনি ব্যবহার করতে পারেন toList(), toSet(), toMap()অথবা অন্য কোনো ফাংশন সত্যে পরিণত Sequenceশেষে।

// switch to and from lazy
val someList = items.asSequence().filter { ... }.take(10).map { ... }.toList()

// switch to lazy, but sorted() brings us out again at the end
val someList = items.asSequence().filter { ... }.take(10).map { ... }.sorted()

সেখানে কোন প্রকারভেদ কেন ?!?

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

val someList = people.filter { it.age <= 30 }.map { it.name }

হিসাবে একই:

val someList: List<String> = people.filter { it.age <= 30 }.map { it.name }

কারণ Kotlin জানেন people, এবং যে people.ageহয় Intসেইজন্য ফিল্টার অভিব্যক্তি শুধুমাত্র একটি তুলনায় পারবেন Int, এবং যে people.nameএকটি হল Stringতাই mapপদক্ষেপ হল একটি উত্পাদন করে List<String>(কেবলমাত্র Listএর String)।

এখন, যদি peopleছিল সম্ভবত null, যেমন-ইন একটি List<People>?তারপর:

val someList = people?.filter { it.age <= 30 }?.map { it.name }

List<String>?এমন একটি ফেরত দেয় যা নাল চেক করা দরকার ( বা নলযোগ্য মানগুলির জন্য অন্য কোটলিন অপারেটরগুলির মধ্যে একটি ব্যবহার করুন, অযোগ্য মানগুলি মোকাবেলা করার জন্য এই কোটলিনের অভিহিত পদ্ধতি এবং কোটলিনে বাতিল বা খালি তালিকা পরিচালনার আইডোমেটিক পদ্ধতিও দেখুন )

আরো দেখুন:


কোটলিনে জাভা 8 এর সমান্তরাল স্ট্রিমের () সমতুল্য?
অর্ণব 25'16

অপরিবর্তনীয় সংগ্রহগুলি এবং Kotlin সম্পর্কে উত্তর @arnab এখানে সমান্তরাল জন্য একই উত্তর, অন্যান্য লাইব্রেরি বিদ্যমান, তাদের ব্যবহার: stackoverflow.com/a/34476880/3679676
জেসন Minard

2
@arnab আপনি Java 7/8 বৈশিষ্ট্যগুলির জন্য Kotlin সমর্থন তাকান (বিশেষ করে, kotlinx-সমর্থন-jdk8 মধ্যে) যে এই বছরের শুরুর দিকে উপলব্ধ করা হয় চাইতে পারেন: discuss.kotlinlang.org/t/jdk7-8-features-in -kotlin-1-0 / 1625
roborative

একটি বিবৃতিতে 3 টি পৃথক "এটি" রেফারেন্স ব্যবহার করা কি সত্যই মূর্খ?
Herman

2
এটি একটি পছন্দ, উপরের নমুনাগুলিতে আমি সেগুলি সংক্ষেপে রাখছিলাম এবং প্রয়োজনে কেবলমাত্র প্যারামিটারের জন্য স্থানীয় নাম সরবরাহ করছি providing
জেসন মিনার্ড

47

অতিরিক্ত উদাহরণগুলির জন্য, জাভা 8 স্ট্রিম টিউটোরিয়াল থেকে সমস্ত নমুনা কোটলিনে রূপান্তরিত। প্রতিটি উদাহরণের শিরোনাম উত্স নিবন্ধ থেকে প্রাপ্ত:

স্ট্রিমগুলি কীভাবে কাজ করে

// Java:
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList.stream()
      .filter(s -> s.startsWith("c"))
      .map(String::toUpperCase)
     .sorted()
     .forEach(System.out::println);

// C1
// C2
// Kotlin:
val list = listOf("a1", "a2", "b1", "c2", "c1")
list.filter { it.startsWith('c') }.map (String::toUpperCase).sorted()
        .forEach (::println)

বিভিন্ন ধরণের স্ট্রিম # 1

// Java:
Arrays.asList("a1", "a2", "a3")
    .stream()
    .findFirst()
    .ifPresent(System.out::println);    
// Kotlin:
listOf("a1", "a2", "a3").firstOrNull()?.apply(::println)

বা, স্ট্রিংয়ে ইফপ্রেসেন্ট নামে একটি এক্সটেনশন ফাংশন তৈরি করুন:

// Kotlin:
inline fun String?.ifPresent(thenDo: (String)->Unit) = this?.apply { thenDo(this) }

// now use the new extension function:
listOf("a1", "a2", "a3").firstOrNull().ifPresent(::println)

এছাড়াও দেখুন: apply()ফাংশন

আরও দেখুন: এক্সটেনশন ফাংশন

এটিও দেখুন: ?.নিরাপদ কল অপারেটর এবং সাধারণভাবে অকার্যকরতা: কোটলিনে, মূল্যহীন মানগুলির সাথে সম্পর্কিত বা রেফারেন্সিং বা রূপান্তরিত করার অলৌকিক উপায় কী?

বিভিন্ন ধরণের স্ট্রিম # 2

// Java:
Stream.of("a1", "a2", "a3")
    .findFirst()
    .ifPresent(System.out::println);    
// Kotlin:
sequenceOf("a1", "a2", "a3").firstOrNull()?.apply(::println)

বিভিন্ন ধরণের স্ট্রিম # 3

// Java:
IntStream.range(1, 4).forEach(System.out::println);
// Kotlin:  (inclusive range)
(1..3).forEach(::println)

বিভিন্ন ধরণের স্ট্রিম # 4

// Java:
Arrays.stream(new int[] {1, 2, 3})
    .map(n -> 2 * n + 1)
    .average()
    .ifPresent(System.out::println); // 5.0    
// Kotlin:
arrayOf(1,2,3).map { 2 * it + 1}.average().apply(::println)

বিভিন্ন ধরণের স্ট্রিম # 5

// Java:
Stream.of("a1", "a2", "a3")
    .map(s -> s.substring(1))
    .mapToInt(Integer::parseInt)
    .max()
    .ifPresent(System.out::println);  // 3
// Kotlin:
sequenceOf("a1", "a2", "a3")
    .map { it.substring(1) }
    .map(String::toInt)
    .max().apply(::println)

বিভিন্ন ধরণের স্ট্রিম # 6

// Java:
IntStream.range(1, 4)
    .mapToObj(i -> "a" + i)
    .forEach(System.out::println);

// a1
// a2
// a3    
// Kotlin:  (inclusive range)
(1..3).map { "a$it" }.forEach(::println)

বিভিন্ন ধরণের স্ট্রিম # 7

// Java:
Stream.of(1.0, 2.0, 3.0)
    .mapToInt(Double::intValue)
    .mapToObj(i -> "a" + i)
    .forEach(System.out::println);

// a1
// a2
// a3
// Kotlin:
sequenceOf(1.0, 2.0, 3.0).map(Double::toInt).map { "a$it" }.forEach(::println)

অর্ডার বিষয়গুলি কেন

জাভা 8 স্ট্রিম টিউটোরিয়ালটির এই বিভাগটি কোটলিন এবং জাভার ক্ষেত্রে একই।

স্ট্রিম পুনরায় ব্যবহার করা হচ্ছে

কোটলিনে এটি একাধিকবার খাওয়া যায় কিনা তা সংগ্রহের ধরণের উপর নির্ভর করে। একটি Sequenceপ্রতিবারই একটি নতুন পুনরুক্তি তৈরি করে এবং যতক্ষণ না এটি "একবার ব্যবহার করুন" হিসাবে দৃ unless় প্রতিপন্ন হয় ততক্ষণে প্রতিটি বার যখন এটি করা হয় তখন এটি পুনরায় সেট করতে পারে can নিম্নলিখিত জাভা 8 প্রবাহে ব্যর্থ হলেও কোটলিনে কাজ করে:

// Java:
Stream<String> stream =
Stream.of("d2", "a2", "b1", "b3", "c").filter(s -> s.startsWith("b"));

stream.anyMatch(s -> true);    // ok
stream.noneMatch(s -> true);   // exception
// Kotlin:  
val stream = listOf("d2", "a2", "b1", "b3", "c").asSequence().filter { it.startsWith('b' ) }

stream.forEach(::println) // b1, b2

println("Any B ${stream.any { it.startsWith('b') }}") // Any B true
println("Any C ${stream.any { it.startsWith('c') }}") // Any C false

stream.forEach(::println) // b1, b2

এবং জাভাতে একই আচরণ পেতে:

// Java:
Supplier<Stream<String>> streamSupplier =
    () -> Stream.of("d2", "a2", "b1", "b3", "c")
          .filter(s -> s.startsWith("a"));

streamSupplier.get().anyMatch(s -> true);   // ok
streamSupplier.get().noneMatch(s -> true);  // ok

সুতরাং কোটলিনে ডেটা সরবরাহকারী সিদ্ধান্ত নেয় যে এটি আবার রিসেট করতে পারে এবং কোনও নতুন পুনরাবৃত্তি সরবরাহ করতে পারে কিনা। তবে আপনি যদি ইচ্ছাকৃতভাবে একবারে Sequenceএক সময়ের পুনরাবৃত্তি সীমাবদ্ধ করতে চান তবে আপনি নীচের হিসাবে constrainOnce()ফাংশনটি ব্যবহার করতে পারেন Sequence:

val stream = listOf("d2", "a2", "b1", "b3", "c").asSequence().filter { it.startsWith('b' ) }
        .constrainOnce()

stream.forEach(::println) // b1, b2
stream.forEach(::println) // Error:java.lang.IllegalStateException: This sequence can be consumed only once. 

উন্নত অপারেশন

# 5 উদাহরণ সংগ্রহ করুন (হ্যাঁ, আমি ইতিমধ্যে অন্যান্য উত্তরে এড়িয়ে গেছি)

// Java:
String phrase = persons
        .stream()
        .filter(p -> p.age >= 18)
        .map(p -> p.name)
        .collect(Collectors.joining(" and ", "In Germany ", " are of legal age."));

    System.out.println(phrase);
    // In Germany Max and Peter and Pamela are of legal age.    
// Kotlin:
val phrase = persons.filter { it.age >= 18 }.map { it.name }
        .joinToString(" and ", "In Germany ", " are of legal age.")

println(phrase)
// In Germany Max and Peter and Pamela are of legal age.

এবং একটি পার্শ্ব নোট হিসাবে, কোটলিনে আমরা সহজ ডেটা ক্লাস তৈরি করতে পারি এবং পরীক্ষার ডেটা নীচে নীচে ইনস্ট্যান্ট করতে পারি:

// Kotlin:
// data class has equals, hashcode, toString, and copy methods automagically
data class Person(val name: String, val age: Int) 

val persons = listOf(Person("Tod", 5), Person("Max", 33), 
                     Person("Frank", 13), Person("Peter", 80),
                     Person("Pamela", 18))

উদাহরণ সংগ্রহ করুন # 6

// Java:
Map<Integer, String> map = persons
        .stream()
        .collect(Collectors.toMap(
                p -> p.age,
                p -> p.name,
                (name1, name2) -> name1 + ";" + name2));

System.out.println(map);
// {18=Max, 23=Peter;Pamela, 12=David}    

ঠিক আছে, এখানে কোটলিনের আরও সুদের মামলা। Mapসংগ্রহ / ক্রম থেকে একটি তৈরির বিভিন্নতার অন্বেষণের জন্য প্রথমে ভুল উত্তরগুলি :

// Kotlin:
val map1 = persons.map { it.age to it.name }.toMap()
println(map1)
// output: {18=Max, 23=Pamela, 12=David} 
// Result: duplicates overridden, no exception similar to Java 8

val map2 = persons.toMap({ it.age }, { it.name })
println(map2)
// output: {18=Max, 23=Pamela, 12=David} 
// Result: same as above, more verbose, duplicates overridden

val map3 = persons.toMapBy { it.age }
println(map3)
// output: {18=Person(name=Max, age=18), 23=Person(name=Pamela, age=23), 12=Person(name=David, age=12)}
// Result: duplicates overridden again

val map4 = persons.groupBy { it.age }
println(map4)
// output: {18=[Person(name=Max, age=18)], 23=[Person(name=Peter, age=23), Person(name=Pamela, age=23)], 12=[Person(name=David, age=12)]}
// Result: closer, but now have a Map<Int, List<Person>> instead of Map<Int, String>

val map5 = persons.groupBy { it.age }.mapValues { it.value.map { it.name } }
println(map5)
// output: {18=[Max], 23=[Peter, Pamela], 12=[David]}
// Result: closer, but now have a Map<Int, List<String>> instead of Map<Int, String>

এবং এখন সঠিক উত্তরের জন্য:

// Kotlin:
val map6 = persons.groupBy { it.age }.mapValues { it.value.joinToString(";") { it.name } }

println(map6)
// output: {18=Max, 23=Peter;Pamela, 12=David}
// Result: YAY!!

তালিকাগুলি ভেঙে ফেলার জন্য আমাদের কেবলমাত্র মিলে যাওয়া মানগুলিতে যোগ দিতে jointToStringহবে এবং Personউদাহরণ থেকে দস্তাবেজে যেতে একটি ট্রান্সফর্মার সরবরাহ করতে হবে Person.name

উদাহরণ সংগ্রহ করুন # 7

ঠিক আছে, এটি সহজেই কোনও প্রথা ছাড়াই করা যায় Collector, সুতরাং আসুন এটি কোটলিন পদ্ধতিতে সমাধান করুন, তারপরে একটি নতুন উদাহরণ তৈরি করুন যা দেখায় যে কীভাবে অনুরূপ প্রক্রিয়া করা যায় Collector.summarizingIntযার জন্য কোটলিনে স্থানীয়ভাবে বিদ্যমান নেই।

// Java:
Collector<Person, StringJoiner, String> personNameCollector =
Collector.of(
        () -> new StringJoiner(" | "),          // supplier
        (j, p) -> j.add(p.name.toUpperCase()),  // accumulator
        (j1, j2) -> j1.merge(j2),               // combiner
        StringJoiner::toString);                // finisher

String names = persons
        .stream()
        .collect(personNameCollector);

System.out.println(names);  // MAX | PETER | PAMELA | DAVID    
// Kotlin:
val names = persons.map { it.name.toUpperCase() }.joinToString(" | ")

এটা আমার ভুল নয় যে তারা একটি তুচ্ছ উদাহরণ বেছে নিয়েছে !!! ঠিক আছে, এখানে summarizingIntকোটলিনের জন্য একটি নতুন পদ্ধতি এবং একটি মিলের নমুনা:

সংক্ষিপ্তকরণের উদাহরণ

// Java:
IntSummaryStatistics ageSummary =
    persons.stream()
           .collect(Collectors.summarizingInt(p -> p.age));

System.out.println(ageSummary);
// IntSummaryStatistics{count=4, sum=76, min=12, average=19.000000, max=23}    
// Kotlin:

// something to hold the stats...
data class SummaryStatisticsInt(var count: Int = 0,  
                                var sum: Int = 0, 
                                var min: Int = Int.MAX_VALUE, 
                                var max: Int = Int.MIN_VALUE, 
                                var avg: Double = 0.0) {
    fun accumulate(newInt: Int): SummaryStatisticsInt {
        count++
        sum += newInt
        min = min.coerceAtMost(newInt)
        max = max.coerceAtLeast(newInt)
        avg = sum.toDouble() / count
        return this
    }
}

// Now manually doing a fold, since Stream.collect is really just a fold
val stats = persons.fold(SummaryStatisticsInt()) { stats, person -> stats.accumulate(person.age) }

println(stats)
// output: SummaryStatisticsInt(count=4, sum=76, min=12, max=23, avg=19.0)

তবে একটি এক্সটেনশন ফাংশন তৈরি করা আরও ভাল, 2 কোটলিন স্ট্যাডলিবের শৈলীর সাথে মেলে

// Kotlin:
inline fun Collection<Int>.summarizingInt(): SummaryStatisticsInt
        = this.fold(SummaryStatisticsInt()) { stats, num -> stats.accumulate(num) }

inline fun <T: Any> Collection<T>.summarizingInt(transform: (T)->Int): SummaryStatisticsInt =
        this.fold(SummaryStatisticsInt()) { stats, item -> stats.accumulate(transform(item)) }

নতুন summarizingIntফাংশনগুলি ব্যবহার করার এখন আপনার কাছে দুটি উপায় রয়েছে :

val stats2 = persons.map { it.age }.summarizingInt()

// or

val stats3 = persons.summarizingInt { it.age }

এবং এই সমস্ত একই ফলাফল উত্পাদন করে। Sequenceযথাযথ আদিম ধরণের উপর কাজ করার জন্য আমরা এই এক্সটেনশনটি তৈরি করতে পারি ।

মজা করার জন্য, জাভা জেডিকে কোড বনাম কোটলিন কাস্টম কোডটির তুলনা করুন এই সংক্ষিপ্তকরণটি বাস্তবায়নের জন্য।


স্ট্রিম 5-এ একের পরিবর্তে দুটি মানচিত্র ব্যবহারের জন্য কোনও প্লাস নেই .map { it.substring(1).toInt() }: আপনি জানেন যে অনুমানযোগ্য টাইপটি কোটলিন শক্তি।
মিশেল ডি'আমিকো

সত্য, তবে কোনও খারাপ দিক নেই (তুলনার জন্য আমি তাদের পৃথক করে রেখেছি)
জেইসন মিনার্ড

তবে জাভা কোডটি সহজেই সমান্তরাল করা যায়, তাই অনেক ক্ষেত্রে কোটলিন থেকে জাভা স্ট্রিম কোডটি কল করা আপনার পক্ষে ভাল।
হাওয়ার্ড লোভাত

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

3

কিছু ক্ষেত্রে রয়েছে যেখানে কল করা collect(Collectors.toList())বা অনুরূপ এড়ানো কঠিন । এই ক্ষেত্রে, আপনি এক্সটেনশন ফাংশনগুলি ব্যবহার করে আরও দ্রুত কোনও কোটলিনের সমতলে পরিবর্তন করতে পারেন যেমন:

fun <T: Any> Stream<T>.toList(): List<T> = this.collect(Collectors.toList<T>())
fun <T: Any> Stream<T>.asSequence(): Sequence<T> = this.iterator().asSequence()

তারপরে আপনি সহজেই stream.toList()বা stream.asSequence()কোটলিন এপিআইতে ফিরে যেতে পারেন । Files.list(path)আপনি Streamযখন না চান এমন ক্ষেত্রে আপনাকে বাধ্য করে এবং এই এক্সটেনশানগুলি আপনাকে স্ট্যান্ডার্ড সংগ্রহ এবং কোটলিন এপিআইতে ফিরে যেতে সহায়তা করতে পারে।


2

অলসতার উপর আরও

জেইসন প্রদত্ত "বিভাগ দ্বারা বেতনের পরিমানের সমষ্টি" এর উদাহরণ সমাধানটি নেওয়া যাক:

val totalByDept = employees.groupBy { it.dept }.mapValues { it.value.sumBy { it.salary }}

এই অলস করতে (অর্থাত্ groupByপদক্ষেপে মধ্যবর্তী মানচিত্র তৈরি করা এড়াতে ), এটি ব্যবহার করা সম্ভব নয় asSequence()। পরিবর্তে, আমাদের অবশ্যই ব্যবহার groupingByএবং foldঅপারেশন করতে হবে:

val totalByDept = employees.groupingBy { it.dept }.fold(0) { acc, e -> acc + e.salary }

কিছু লোকের কাছে এটি আরও পঠনযোগ্য হতে পারে, যেহেতু আপনি মানচিত্রের এন্ট্রিগুলি নিয়ে কাজ করছেন না: it.valueসমাধানটির অংশটি আমার জন্য প্রথমে বিভ্রান্তিকর ছিল।

যেহেতু এটি একটি সাধারণ ঘটনা এবং আমরা foldপ্রতিটি সময় লিখতে পছন্দ করি না , কেবল জেনেরিক sumByফাংশন সরবরাহ করা ভাল হতে পারে Grouping:

public inline fun <T, K> Grouping<T, K>.sumBy(
        selector: (T) -> Int
): Map<K, Int> = 
        fold(0) { acc, element -> acc + selector(element) }

যাতে আমরা সহজভাবে লিখতে পারি:

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