ToB企服应用市场:ToB评测及商务社交产业平台

标题: 从头学Java17-今天的Kotlin更香吗 [打印本页]

作者: 耶耶耶耶耶    时间: 2023-7-15 16:56
标题: 从头学Java17-今天的Kotlin更香吗
出于各种限制,很多公司依然停留在Java8,部分小伙伴转向了Kotlin。Kotlin作为静态编译语言,提供大量语法糖,而且编译后的字节码跟Java一致。
当时,Java8于2014年发布,Kotlin于2016年,很多宣称的语法糖都是对比的Java8。不禁要问,相对今天的Java17,Kotlin优势还在吗?
现在就用最新的Kotlin1.9.0,对前三篇文章里的lambda、StreamAPI依次改造,实践出真知!

编写lambda、调用

Java
  1. import Java.util.*;
  2. import Java.util.function.*;
  3. /**
  4. *
  5. * @author 烧哥burn.red
  6. */
  7. public class Test1 {
  8.    
  9.     public static void main(String[] args) {
  10.         
  11.         Predicate<String> predicate = s -> s.length() == 3;
  12.         Consumer<String> consumer = s -> System.out.println(s);
  13.         Supplier<String> supplier = () -> "Hello Duke!";
  14.         Function<String, Integer> function = s -> s.length();
  15.         
  16.         IntSupplier intSupplier = () -> 1;
  17.         IntConsumer intConsumer = s -> System.out.println(s);
  18.         IntPredicate intPredicate = i -> i > 10;
  19.         ToIntFunction<String> toIntFunction = s -> s.length();
  20.         UnaryOperator<String> unaryOperator = s -> s.toUpperCase();
  21.         
  22.         BiConsumer<String, Integer> biConsumer = (s, number) -> s.indexOf(number);
  23.         ObjIntConsumer<String> objIntConsumer = (s, value) -> System.out.printf("%s,%d\n", s, value);
  24.         BiPredicate<String, Integer> biPredicate = (word, length) -> word.length() == length;
  25.         BiFunction<String, String, Integer> biFunction = (word, sentence) -> sentence.indexOf(word);
  26.         ToIntBiFunction<String, String> toIntBiFunction = (word, sentence) -> sentence.indexOf(word);
  27.         
  28.         String a = "aaa";
  29.         
  30.         if (predicate.test(a)) {
  31.             consumer.accept(a);
  32.             supplier.get();
  33.             function.apply(a);
  34.             
  35.             intConsumer.accept(1);
  36.             intSupplier.getAsInt();
  37.             intPredicate.test(11);
  38.             toIntFunction.applyAsInt(a);
  39.             unaryOperator.apply(a);
  40.             
  41.             biConsumer.accept(a, 2);
  42.             objIntConsumer.accept(null, 1);
  43.             biPredicate.test(a, 3);
  44.             biFunction.apply("fdsa", a);
  45.             toIntBiFunction.applyAsInt("fdsa", a);
  46.         }
  47.         List<String> strings = new ArrayList<>(List.of("a", "bb", "ccc"));
  48.         strings.forEach(consumer);
  49.         strings.removeIf(predicate);//不应该在不可变集合上调用
  50.         System.out.println(strings);
  51.         
  52.         strings = Arrays.asList("a", "bb", "ccc");
  53.         strings.replaceAll(unaryOperator);
  54.         System.out.println(strings);
  55. //        int i = 0;
  56. //        Consumer<Integer> add = s -> i++;//报错,从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
  57.     }
  58. }
复制代码
Kotlin
  1. /**
  2. *
  3. * @author 烧哥burn.red
  4. */
  5. fun main() {
  6.     val predicate = { s: String -> s.length == 3 }
  7.     val consumer = { s: String? -> println(s) }
  8.     val supplier = { "Hello Duke!" }
  9.     val function = { s: String -> s.length }
  10.     val intSupplier = { 1 }
  11.     val intConsumer = { s: Int -> println(s) }
  12.     val intPredicate = { i: Int -> i > 10 }
  13.     val toIntFunction = { s: String -> s.length }
  14.     val unaryOperator = { s: String -> s.uppercase() }
  15.     val biConsumer = { s: String, number: Int -> s.indexOf(number.toChar()) }
  16.     val objIntConsumer = { s: String?, value: Int -> println("$s,$value") }
  17.     val biPredicate = { word: String, length: Int -> word.length == length }
  18.     val biFunction = { word: String?, sentence: String -> sentence.indexOf(word!!) }
  19.     val toIntBiFunction = { word: String?, sentence: String -> sentence.indexOf(word!!) }
  20.     val a = "aaa"
  21.     if (predicate(a)) {
  22.         consumer(a)
  23.         supplier()
  24.         function(a)
  25.         intConsumer(1)
  26.         intSupplier()
  27.         intPredicate(11)
  28.         toIntFunction(a)
  29.         unaryOperator(a)
  30.         biConsumer(a, 2)
  31.         objIntConsumer(null, 1)
  32.         biPredicate(a, 3)
  33.         biFunction("fdsa", a)
  34.         toIntBiFunction("fdsa", a)
  35.     }
  36.     var strings = mutableListOf("a", "bb", "ccc")
  37.     strings.forEach(consumer)
  38.     strings.removeIf(predicate) //不应该在不可变集合上调用
  39.     println(strings)
  40.     strings = arrayListOf("a", "bb", "ccc")
  41.     strings.replaceAll(unaryOperator)
  42.     println(strings)
  43.     var i = 0
  44.     val add = { s: Int? -> i++ } //不报错
  45.     add(i)
  46.     println(i)
  47. }
复制代码
可以看出:
这一局,Kotlin胜出。
方法引用、链接

Java
  1. import red.burn.bean.User;
  2. import Java.util.*;
  3. import Java.util.function.*;
  4. import Java.util.logging.Logger;
  5. /**
  6. * @author 烧哥burn.red
  7. */
  8. public class Test2 {
  9.     public static void main(String[] args) {
  10.         //方法引用
  11.         DoubleUnaryOperator sqrt = Math::sqrt;
  12.         IntBinaryOperator max = Integer::max;//静态方法引用
  13.         Supplier<List<String>> newListOfStrings = ArrayList::new;//构造方法引用
  14.         Consumer<String> printer = System.out::println;//绑定到System.out
  15.         Function<String, Integer> toLength = String::length;//非绑定,绑定到String的实例
  16.         //Lambla的链接
  17.         Predicate<String> isNull = Objects::isNull;
  18.         Predicate<String> isEmpty = String::isEmpty;
  19.         Predicate<String> isNullOrEmpty = isNull.or(isEmpty);
  20.         Predicate<String> isNotNullNorEmpty = isNullOrEmpty.negate();
  21.         Predicate<String> shorterThan5 = s -> s.length() < 5;
  22.         Predicate<String> p = isNotNullNorEmpty.and(shorterThan5);
  23.         Logger logger = Logger.getLogger("MyApplicationLogger");
  24.         Consumer<String> log = logger::info;
  25.         Consumer<String> printStr = System.out::println;
  26.         Consumer<String> printAndLog = log.andThen(printStr);//
  27.         printAndLog.accept("test");
  28.         Function<String, Integer> function1 = String::length;
  29.         Function<Integer, Integer> function2 = s -> ++s;
  30.         Function<String, Integer> function = function1.andThen(function2);
  31.         System.out.println("new=" + function.apply("abc")); //4
  32.         Function<String, String> id = Function.identity();
  33.         //Comparator
  34.         Comparator<Integer> comparator = Integer::compare;
  35.         Comparator<String> comparator1 = (s1, s2) -> Integer.compare(s1.length(), s2.length());
  36.         Comparator<String> comparator2 = (s1, s2) -> Integer.compare(toLength.apply(s1), toLength.apply(s2));
  37.         Comparator<String> comparator3 = Comparator.comparing(String::length);
  38.         Comparator<User> byFirstName = Comparator.comparing(User::getFirstName);
  39.         Comparator<User> byLastName = Comparator.comparing(User::getLastName);
  40.         Comparator<User> byFirstNameThenLastName = byFirstName.thenComparing(byLastName)
  41.                                                               .thenComparingInt(User::getAge);
  42.         Comparator<User> byFirstNameThenLastName1 = Comparator.comparingInt(User::getAge)
  43.                                                               .thenComparing(
  44.                                                                       Comparator.nullsLast(Comparator.naturalOrder()));
  45.         List<String> strings = Arrays.asList("one", "two", "three", "four", "five");
  46.         strings.sort(comparator3.reversed());
  47.         System.out.println(strings);
  48.     }
  49. }
复制代码
  1. import lombok.Builder;
  2. import lombok.Data;
  3. import org.jetbrains.annotations.NotNull;
  4. /**
  5. * @author 烧哥burn.red
  6. */
  7. @Data
  8. @Builder
  9. public class User implements Comparable<User> {
  10.     private String name;
  11.     private int age;
  12.     private String firstName;
  13.     private String lastName;
  14.     @Override
  15.     public int compareTo(User o) {
  16.         return this.name.compareTo(o.name);
  17.     }
  18. }
复制代码
Kotlin
  1. import Java.util.logging.Logger
  2. import Kotlin.math.sqrt
  3. import red.burn.bean.UserKT
  4. import Kotlin.math.max
  5. /**
  6. *
  7. * @author 烧哥burn.red
  8. */
  9. fun main() {
  10.     //方法引用
  11.     val sqrt = ::sqrt
  12. //    val max = ::max //报错,歧义
  13. //    val newListOfStrings = ::ArrayList  //报错,歧义
  14. //    val printer =::println //报错,歧义
  15.     val ar = 5.run<Int, ArrayList<String>>(::ArrayList)
  16.     "a".run(::println)
  17.     val kt = ::UserKT //构造方法引用
  18.     val user = kt("abc", 10)
  19.     var (name, age) = UserKT("csc")
  20.     val firstName = user::firstName //属性引用
  21.     val addAge = user::addAge //函数引用
  22.     val toLength = String::length  //非绑定,绑定到String的实例
  23.     //Lambla的链接
  24.     val isNull = { obj: String? -> obj == null }
  25.     val isEmpty = { obj: String -> obj.isEmpty() }
  26.     val isNullOrEmpty = { obj: String? -> obj == null || isEmpty(obj) }
  27.     val isNotNullNorEmpty = { obj: String? -> !isNullOrEmpty(obj) }
  28.     val shorterThan5 = { s: String -> s.length < 5 }
  29.     val p = { s: String -> isNotNullNorEmpty(s).and(shorterThan5(s)) }
  30.     val logger = Logger.getLogger("MyApplicationLogger")
  31.     val log = { message: String? -> logger.info(message) }
  32.     val printStr = { message: String? -> println(message) }
  33.     val printAndLog = { message: String? ->
  34.         log(message).also { printStr(message) }
  35.     }
  36.     printAndLog("test")
  37.     val function1 = String::length
  38. //    val function2 = {  s: Int -> ++s }//报错 Val cannot be reassigned
  39.     val function2 = { s: Int ->
  40.         var i = s;
  41.         ++i;
  42.     }
  43.     val function = { s: String -> function1(s).let(function2) }
  44.     println("new=" + function("abc")) //4
  45.     val id = { s: String? -> s }
  46.     //Comparator
  47.     val comparator = { x: Int, y: Int -> (x).compareTo(y) }
  48.     val comparator1 = { s1: String, s2: String -> s1.length.compareTo(s2.length) }
  49.     val comparator2 = { s1: String, s2: String -> toLength(s1).compareTo(toLength(s2)) }
  50.     val comparator3 = compareBy(String::length)
  51.     val byFirstName = compareBy(UserKT::firstName)
  52.     val byLastName = compareBy(UserKT::lastName)
  53.     val byFirstNameThenLastName = byFirstName.then(byLastName).thenBy(UserKT::age)
  54.     val byFirstNameThenLastName1 = compareBy(UserKT::age).then(nullsLast(naturalOrder()))
  55.     val strings = arrayListOf("one", "two", "three", "four", "five")
  56.     strings.sortWith(comparator3.reversed())
  57.     println(strings)
  58. }
复制代码
  1. /**
  2. *
  3. * @author 烧哥burn.red
  4. */
  5. data class UserKT(var name: String, var age: Int = 1) : Comparable<UserKT> {
  6.     var firstName: String? = null
  7.     var lastName: String? = null
  8.     override fun compareTo(other: UserKT): Int {
  9.         return name.compareTo(other.name)
  10.     }
  11.     fun printUser(s: UserKT) {
  12.         println(s)
  13.     }
  14.     fun addAge(i: Int, j: Int): Int {
  15.         return i + j
  16.     }
  17. }
复制代码
可以看出:
这一局,Kotlin跟Java打平。
StreamAPI

Java
  1. import Java.util.List;
  2. import Java.util.Map;
  3. import Java.util.function.*;
  4. import Java.util.stream.*;
  5. /**
  6. * @author 烧哥burn.red
  7. */
  8. public class Test3 {
  9.    
  10.     public static void main(String[] args) {
  11.         
  12.         //flatmap
  13.         Function<String, Stream<Integer>> flatParser = s -> {
  14.             try {
  15.                 return Stream.of(Integer.parseInt(s));
  16.             } catch (NumberFormatException e) {
  17.             }
  18.             return Stream.empty();
  19.         };
  20.         
  21.         List<String> strings = List.of("1", " ", "2", "3 ", "", "3");
  22.         List<Integer> ints = strings.stream().flatMap(flatParser).toList();
  23.         System.out.println("ints = " + ints);
  24.         
  25.         //mapMulti
  26.         ints = strings.stream().<Integer>mapMulti((string, consumer) -> {
  27.             try {
  28.                 consumer.accept(Integer.parseInt(string));
  29.             } catch (NumberFormatException ignored) {
  30.             }
  31.         }).toList();
  32.         System.out.println("ints = " + ints);
  33.         
  34.         List<Integer> ints2 = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
  35.         List<Integer> result = ints2.stream().skip(2).limit(5).toList();
  36.         System.out.println("result = " + result);
  37.         
  38.         List<Integer> list0 = List.of(1, 2, 3);
  39.         List<Integer> list1 = List.of(4, 5, 6);
  40.         List<Integer> list2 = List.of(7, 8, 9);
  41. // 1st pattern: concat
  42.         List<Integer> concat = Stream.concat(list0.stream(), list1.stream()).toList();
  43. // 2nd pattern: flatMap
  44.         List<Integer> flatMap = Stream.of(list0.stream(), list1.stream(), list2.stream())//类似city的外层组成的流
  45.                                       .flatMap(Function.identity()).toList();
  46.         System.out.println("concat  = " + concat);
  47.         System.out.println("flatMap = " + flatMap);
  48.         
  49.         //reduce
  50.         Stream<String> strings1 = Stream.of("one", "two", "three", "four");
  51.         BinaryOperator<Integer> combiner = Integer::sum;
  52.         Function<String, Integer> mapper = String::length;
  53.         BiFunction<Integer, String, Integer> accumulator = (partialReduction, element) -> partialReduction + mapper.apply(element);
  54.         int result1 = strings1.reduce(0, accumulator, combiner);
  55.         System.out.println("sum = " + result1);
  56.         
  57.         //groupby map
  58.         List<String> strings2 = List.of("two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve");
  59.         Map<Integer, Long> histogram = strings2.stream().collect(Collectors.groupingBy(String::length, Collectors.counting()));
  60.         histogram.forEach((k, v) -> System.out.println(k + " :: " + v));
  61.         
  62.         Map<Long, List<Integer>> map = histogram.entrySet()
  63.                                                 .stream()
  64.                                                 .collect(Collectors.groupingBy(Map.Entry::getValue,
  65.                                                                                Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
  66.         Map.Entry<Long, List<Integer>> result2 = map.entrySet().stream().max(Map.Entry.comparingByKey())//再求max
  67.                                                     .orElseThrow();
  68.         System.out.println("result = " + result2);
  69.     }
  70. }
复制代码
Kotlin
  1. /**
  2. * @author 烧哥burn.red
  3. */
  4. fun main() {
  5.    
  6.     //flatmap
  7.     val flatParser = label@{ s: String ->
  8.         try {
  9.             return@label listOf(s.toInt())
  10.         } catch (_: NumberFormatException) {
  11.         }
  12.         emptyList<Int>()
  13.     }
  14.     val strings = listOf("1", " ", "2", "3 ", "", "3")
  15.     var ints = strings.flatMap(flatParser)
  16.     println("ints = $ints")
  17.     //mapMulti
  18.     /*ints = strings.mapMulti { string: String, consumer: Consumer<Int?> ->
  19.             try {
  20.                 consumer.accept(string.toInt())
  21.             } catch (ignored: NumberFormatException) {
  22.             }
  23.         }
  24.     println("ints = $ints")*/
  25.     val ints2 = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
  26.     val result = ints2.drop(2).take(5)
  27.     println("result = $result")
  28.     val list0 = listOf(1, 2, 3)
  29.     val list1 = listOf(4, 5, 6)
  30.     val list2 = listOf(7, 8, 9)
  31. // 1st pattern: concat
  32.     val concat = list0 + list1
  33. // 2nd pattern: flatMap
  34.     val flatMap = listOf(list0, list1, list2).flatten()
  35.     println("concat  = $concat")
  36.     println("flatMap = $flatMap")
  37.     //reduce
  38.     val strings1 = listOf("one", "two", "three", "four")
  39.     val mapper = String::length
  40.     val accumulator = { partialReduction: Int, element: String -> partialReduction + mapper(element) }
  41.     val result1 = strings1.fold(0, accumulator)
  42.     println("sum = $result1")
  43.      //groupby map
  44.     val strings2 = listOf("two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve")
  45.     val histogram: Map<Int, Int> = strings2.groupingBy { it.length }.eachCount()
  46.     histogram.forEach({ k, v -> println("$k :: $v") })
  47.     val map = histogram.map { it }.groupBy({ it.value }, { it.key }).maxBy { it.key }
  48.     println(map)
  49. }
复制代码
可以看出:
总体来说,代码量减少非常多,这局Kotlin胜出。
综合

Java
  1. import red.burn.bean.*;
  2. import Java.util.*;
  3. import Java.util.function.BiFunction;
  4. import Java.util.function.Function;
  5. import Java.util.stream.*;
  6. /**
  7. *
  8. * @author 烧哥burn.red
  9. */
  10. public class Test4 {
  11.    
  12.     public static void main(String[] args) {
  13.         
  14.         Author au1 = new Author("Au1");
  15.         Author au2 = new Author("Au2");
  16.         Author au3 = new Author("Au3");
  17.         Author au4 = new Author("Au4");
  18.         Author au5 = new Author("Au5");
  19.         Article a1 = new Article("a1", 1991, List.of(au1));
  20.         Article a2 = new Article("a2", 1992, List.of(au1, au2));
  21.         Article a3 = new Article("a3", 1993, List.of(au1, au3, au4));
  22.         Article a4 = new Article("a4", 1992, List.of(au1, au2, au3, au4));
  23.         List<Article> articles = List.of(a1, a2, a3, a4);
  24.         
  25.         BiFunction<Article, Author, Stream<PairOfAuthors>> buildPairOfAuthors =
  26.                 (article, firstAuthor) -> article.authors().stream().flatMap(
  27.                         secondAuthor -> PairOfAuthors.of(firstAuthor, secondAuthor).stream());//Optional的Stream
  28.         
  29.         Function<Article, Stream<PairOfAuthors>> toPairOfAuthors =
  30.                 article -> article.authors().stream().flatMap(firstAuthor -> buildPairOfAuthors.apply(article, firstAuthor));
  31.         Collector<PairOfAuthors, ?, Map<PairOfAuthors, Long>> collector1 =
  32.                 Collectors.groupingBy(Function.identity(), Collectors.counting());
  33. //        System.out.println("numberOfAuthorsTogether=" + numberOfAuthorsTogether);
  34.         Function<Map<PairOfAuthors, Long>, Map.Entry<PairOfAuthors, Long>> finisher1 =
  35.                 map1 -> map1.entrySet().stream().max(Map.Entry.comparingByValue()).orElseThrow();
  36.         
  37.         Map.Entry<PairOfAuthors, Long> result11 =
  38.                 articles.stream().flatMap(toPairOfAuthors).collect(Collectors.collectingAndThen(collector1, finisher1));
  39.         
  40.         Map.Entry<PairOfAuthors, Long> result12 =
  41.                 articles.stream().collect(Collectors.flatMapping(toPairOfAuthors, Collectors.collectingAndThen(collector1, finisher1)));
  42.         
  43.         //找出每年发表文章最多的两位联合作者
  44.         Collector<Article, ?, Optional<Map.Entry<PairOfAuthors, Long>>> flatMapping = Collectors.flatMapping(toPairOfAuthors,
  45.                                                                                                              Collectors.collectingAndThen(
  46.                                                                                                                      collector1,
  47.                                                                                                                      map2 -> map2.entrySet()
  48.                                                                                                                                  .stream()
  49.                                                                                                                                  .max(Map.Entry.comparingByValue())));
  50.         Map<Integer, Optional<Map.Entry<PairOfAuthors, Long>>> result13 =
  51.                 articles.stream().collect(Collectors.groupingBy(Article::inceptionYear, flatMapping));
  52.         Map<Integer, Map.Entry<PairOfAuthors, Long>> result14 = result13.entrySet()
  53.                                                                         .stream()
  54.                                                                         .flatMap(entry -> entry.getValue()
  55.                                                                                                .map(value -> Map.entry(entry.getKey(),
  56.                                                                                                                        value))
  57.                                                                                                .stream())
  58.                                                                         .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  59.         
  60.         System.out.println(result11);
  61.         System.out.println(result12);
  62.         System.out.println(result13);
  63.         System.out.println(result14);
  64.     }
  65. }
复制代码
  1. public record Article(String title, int inceptionYear, List<Author> authors) {
  2. }
  3. public record Author(String name) implements Comparable<Author> {
  4.    
  5.     public int compareTo(Author other) {
  6.         
  7.         return this.name.compareTo(other.name);
  8.     }
  9. }
  10. public record PairOfAuthors(Author first, Author second) {
  11.    
  12.     public static Optional<PairOfAuthors> of(Author first, Author second) {
  13.         
  14.         if (first.compareTo(second) > 0) {
  15.             return Optional.of(new PairOfAuthors(first, second));
  16.         } else {
  17.             return Optional.empty();
  18.         }
  19.     }
  20. }
复制代码
Kotlin
[code][/code]可以看出:
这局Java胜。
最终

Kotlin以2:1微弱优势胜出。
Java用他的严谨,证明能实现从简单到复杂的各种场景。
Kotlin用它的简洁,通常情况下能减少工作量。
Kotlin还提供了委托、扩展、运算符重载、作用域函数、协程等等。
子曾经曰过”越简洁,越有坑“。想完全用Kotlin取代Java,还有一段路,目前二者可以互操作,建议同时使用。
复杂场景下,用什么语言并不是决定性的,解决方案才是。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4