खोज…


परिचय

कोटलिन कार्यात्मक-शैली संचालन को लागू करने के लिए संग्रह और पुनरावृत्तियों पर कई विस्तार विधियां प्रदान करता है। एक समर्पित Sequence प्रकार ऐसे कई कार्यों की आलसी संरचना के लिए अनुमति देता है।

टिप्पणियों

आलस्य के बारे में

यदि आप किसी श्रृंखला को आलसी करना चाहते हैं, तो आप श्रृंखला से पहले asSequence() का उपयोग करके Sequence परिवर्तित कर सकते हैं। कार्यों की श्रृंखला के अंत में, आप आमतौर पर एक 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()

कोई प्रकार क्यों नहीं हैं?

आप ध्यान देंगे कि कोटलिन के उदाहरण प्रकारों को निर्दिष्ट नहीं करते हैं। इसका कारण यह है कि कोटलिन में पूर्ण प्रकार का अनुमान है और संकलन के समय पूरी तरह से सुरक्षित है। जावा से अधिक इसलिए क्योंकि इसमें अशक्त प्रकार भी हैं और यह खतरनाक NPE को रोकने में मदद कर सकता है। तो कोटलिन में यह:

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>? देता है List<String>? यह अशक्त मूल्यों के लिए किसी अन्य कोटलीन ऑपरेटर की जाँच करने के लिए ( या उपयोग करने की आवश्यकता होगी , इस कोटलीन मुहावरेदार तरीके को अशक्त मानों से निपटने के लिए और कोटलिन में अशक्त या खाली सूची से निपटने का मुहावरेदार तरीका देखें )

पुन: उपयोग की धाराएँ

कोटलिन में, यह संग्रह के प्रकार पर निर्भर करता है कि क्या इसका एक से अधिक बार सेवन किया जा सकता है। एक Sequence हर बार एक नया पुनरावृत्ति उत्पन्न करता है, और जब तक यह "केवल एक बार उपयोग" का दावा नहीं करता है, तब तक इसे हर बार शुरू होने पर रीसेट किया जा सकता है। इसलिए जावा 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. 

यह सभी देखें:

एक सूची में नाम संचित करें

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

तत्व को स्ट्रिंग्स में परिवर्तित करें और उन्हें अलग करें, अल्पविराम द्वारा अलग किया गया

// Java:
String joined = things.stream()
                       .map(Object::toString)
                       .collect(Collectors.joining(", "));
// Kotlin:
val joined = things.joinToString() // ", " is used as separator, by default

कर्मचारी के वेतन की गणना योग

// 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> namesOfMaleMembersCollect = 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 { item.startsWith('o') } 

सबसे छोटी स्ट्रिंग एक सूची ढूँढना

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

धारा # 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 के विभिन्न प्रकार - lazily iterate डबल्स, Int का नक्शा, स्ट्रिंग का मैप, प्रत्येक को प्रिंट करें

// 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)

फ़िल्टर लागू होने के बाद किसी सूची में आइटम की गणना करना

// 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') }

धाराएँ कैसे काम करती हैं - फ़िल्टर, ऊपरी मामला, फिर एक सूची को क्रमबद्ध करें

// 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)

या, स्ट्रिंग पर एक विस्तार फ़ंक्शन बनाएं जिसे ifPresent कहा जाता है:

// 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() फ़ंक्शन

इन्हें भी देखें: एक्सटेंशन फ़ंक्शंस

इसे भी देखें ?. सुरक्षित कॉल ऑपरेटर , और सामान्य रूप से अशक्तता में: http://stackoverflow.com/questions/34498562/in-kotlin-what-is-the-idiomatic-way-to-deal-with-nullable-values-referencing-o/34498563 # 34498563

उदाहरण # 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!!

हमें सूचियों को संक्षिप्त करने के लिए मिलान मूल्यों में शामिल होने की जरूरत है और एक उदाहरण के लिए Person.name उदाहरण से Person लिए स्थानांतरित करने के लिए joinToString एक ट्रांसफार्मर प्रदान Person.name

उदाहरण # 7a लीजिए - मानचित्र के नाम, सीमांकक के साथ मिलकर

// Java (verbose):
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    

// Java (concise)
String names = persons.stream().map(p -> p.name.toUpperCase()).collect(Collectors.joining(" | "));
// Kotlin:
val names = persons.map { it.name.toUpperCase() }.joinToString(" | ")

उदाहरण # 7b लीजिए - 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 वास्तव में कोटलिन stdlib में शैलियों से मेल खाने के लिए:

// 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 पर काम करने के लिए और उपयुक्त आदिम प्रकारों के लिए भी बना सकते हैं।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow