अतिरिक्त उदाहरणों के लिए, यहाँ जावा 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)
या, स्ट्रिंग पर एक एक्सटेंशन फ़ंक्शन बनाएं जिसे ifresent कहा जाता है:
// 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
एक नया इटरेटर हर बार उत्पन्न करता है, और हर बार यह पर काम किया जाता है, जब तक यह शुरू "उपयोग केवल एक बार" का दावा है उसे रीसेट कर सकते। इसलिए जब जावा 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
कोटलिन और एक मिलान नमूने के लिए एक नई विधि है:
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
उचित आदिम प्रकारों पर काम करने के लिए भी बना सकते हैं ।
मज़े के लिए, इस संक्षेप को लागू करने के लिए आवश्यक जावा JDK कोड बनाम कोटलिन कस्टम कोड की तुलना करें ।
collect(Collectors.toList())
या इसी तरह का कोई विकल्प नहीं है , आप इस मुद्दे को मार सकते हैं: stackoverflow.com/a/35722167/3679676 (समस्या, वर्कअराउंड के साथ)