【原创】经验分享(17)编程实践对比Java vs Scala

scala

官方地址 https://www.scala-lang.org/

本文尽可能包含了一些主要的java和scala在编程实践时的显著差异,展现scala的代码的简洁优雅;scala通吃面向对象编程Object Oriented Programming和函数式编程Functional Programming,有很多开源组件都用scala开发(比如spark、kafka等),直接看代码对比;

一 Loop循环

1 for

取出0-10之间的偶数

scala

    for (i <- 0 to 10 if i % 2 == 0) println(i)
    //or
    for (i <- 0 to 5) println(i * 2)
    //or
    for (i <- 0 until 6) println(i * 2)

java

        for (int i = 0; i <= 10; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
            }
        }
        //or
        for (int i = 0; i <= 10; i += 2) {
            System.out.println(i);
        }
        //or
        for (int i = 0; i <= 5; i++) {
            System.out.println(i * 2);
        }

输出
0
2
4
6
8
10

2 foreach

迭代输出

scala

val list = List(2, 4, 1, 3, 5)
list.foreach(println)

java

        List<Integer> list = Arrays.asList(new Integer[]{2, 4, 1, 3, 5});
        for (Integer item : list) {
            System.out.println(item);
        }
        //or
        list.forEach((item) -> System.out.println(item));

输出
2
4
1
3
5

二 Functional函数式

函数式即将函数作为变量的一种,来看常见的包装应用

scala

    def wrapper(str : String, f : ((String) => String)): Unit = {
      println("wrapper start")
      println(f(str))
      println("wrapper end")
    }
    def say(str : String) : String = "hello " + str
    wrapper("test", say)
    //or
    wrapper("test", (str => "hello " + str))

java

    interface SayInterface {
        public String say(String str);
    }
    public void wrapper1(String str, SayInterface si) {
        System.out.println("wrapper start");
        System.out.println(si.say(str));
        System.out.println("wrapper end");
    }
    //or
    public void wrapper2(String str, Function<String, String> f) {
        System.out.println("wrapper start");
        System.out.println(f.apply(str));
        System.out.println("wrapper end");
    }

        this.wrapper1("test", new SayInterface() {
            @Override
            public String say(String str) {
                return "hello " + str;
            }
        });
        //or
        this.wrapper1("test", ((item) -> "hello " + item));
        //or
        this.wrapper2("test", ((item) -> "hello " + item));

在早期的Java中函数式等价于命令模式,需要定义一个命令接口,然后可以传入不同的接口实现,这样又形成策略模式,比如jdk的排序接口;

输出
wrapper start
hello test
wrapper end

三 Array Collection

1 数组相加

scala

    val arr1 = Array(1, 2)
    val arr2 = ArrayBuffer(1, 3)
    arr2 += (4)
    val arr3 = arr1 ++ arr2
    println(arr3.mkString(","))

java

        Integer[] arr1 = new Integer[]{1, 2};
        Integer[] arr2 = new Integer[]{1, 3};
        Integer[] arr3 = new Integer[arr1.length + arr2.length];
        for (int i = 0; i < arr1.length; i++) {
            arr3[i] = arr1[i];
        }
        for (int i = 0; i < arr2.length; i++) {
            arr3[arr1.length + i] = arr2[i];
        }
        for (Integer item : arr3) {
            System.out.println(item);
        }
        //or
        List<Integer> list = new ArrayList<>();
        list.addAll(Arrays.asList(arr2));
        list.addAll(Arrays.asList(arr3));
        list.add(4);
        list.forEach((item) -> System.out.println(item));

输出
1,2,1,3

2 创建Map及添加entry

scala

//    val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3)
    var map1 = Map("a" -> 1, "b" -> 2)
    map1 += ("c" -> 3)
    map1.foreach(println)

java

        Map<String, Integer> map1 = new HashMap<>();
        map1.put("a", 1);
        map1.put("b", 2);
        map1.put("c", 3);
        map1.forEach((key, value) -> System.out.println(key + ", " + value));

输出
(a,1)
(b,2)
(c,3)

3 合并两个Map

两个Map中key相同时将value相加

scala

    val map1 = Map("a" -> 1, "b" -> 2)
    val map2 = Map("a" -> 1, "c" -> 3)
    Array.concat(map1.toArray, map2.toArray).groupBy(_._1).map(item => (item._1, item._2.map(_._2).reduce(_ + _))).foreach(println)

java

        Map<String, Integer> map1 = new HashMap<>();
        map1.put("a", 1);
        map1.put("b", 2);
        Map<String, Integer> map2 = new HashMap<>();
        map2.put("a", 1);
        map2.put("c", 3);
        //merge map1 and map2 to mapMerge
        Map<String, Integer> mapMerge = new HashMap<>();
        mapMerge.putAll(map1);
        for (String key : map2.keySet()) {
            if (mapMerge.containsKey(key)) {
                mapMerge.put(key, mapMerge.get(key) + map2.get(key));
            } else {
                mapMerge.put(key, map2.get(key));
            }
        }
        mapMerge.forEach((key, value) -> System.out.println(key + ", " + value));

输出
(b,2)
(a,2)
(c,3)

4 mkString

将集合元素逗号分隔输出

scala

    val arr = Array(2, 4, 1, 3, 5)
    println(arr.mkString(","))

java

    public String mkStringInJava(Object[] arr, String seperator) {
        StringBuffer buf = new StringBuffer();
        for (Object item : arr) {
            buf.append(seperator).append(item);
        }
        return buf.toString().substring(seperator.length());
    }

        Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
        System.out.println(this.mkStringInJava(arr, ","));

输出
2,4,1,3,5

5 统计最小、最大、平均值

scala

    val arr = Array(2, 4, 1, 3, 5)
    println(arr.min + ", " + arr.max + ", " + arr.sum.toDouble / arr.length)

java

        Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
        Integer min = null;
        Integer max = null;
        Integer sum = 0;
        for (Integer item : arr) {
            sum += item;
            if (min == null || min > item) {
                min = item;
            }
            if (max == null || max < item) {
                max = item;
            }
        }
        System.out.println(min + ", " + max + ", " + ((double)sum / arr.length));

输出
1, 5, 3.0

6 简单排序

正序、倒叙

scala

    val arr = Array(2, 4, 1, 3, 5)
    //1
    println(arr.sorted.mkString(","))
    //2
    println(arr.sorted.reverse.mkString(","))
    //3
    println(arr.sortWith((v1 : Int, v2 : Int) => v2 < v1).mkString(","))

java

        Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
        //1
        Arrays.sort(arr);
        for (Integer item : arr) {
            System.out.println(item);
        }
        //or
        Arrays.asList(arr).forEach((v) -> System.out.println(v));
        //2
        for (int i = arr.length - 1; i >= 0; i--) {
            System.out.println(arr[i]);
        }
        //3
        Arrays.sort(arr, new Comparator<Integer>(){
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        //or
        Arrays.sort(arr, ((Integer v1, Integer v2) -> v2 - v1));
        for (Integer item : arr) {
            System.out.println(item);
        }

输出
1,2,3,4,5
5,4,3,2,1
5,4,3,2,1

7 flatMap distinct

将数组中每个元素拆成多个元素并去重

scala

    val arr = Array("1,2,3", "1,4,5")
    arr.flatMap(_.split(",")).distinct.foreach(println)

java

        String[] arr = new String[]{"1,2,3", "1,4,5"};
        Set<String> set = new HashSet<>();
        for (String item : arr) {
            set.addAll(Arrays.asList(item.split(",")));
        }
        set.forEach((item) -> System.out.println(item));

输出
1
2
3
4
5

8 foldLeft

将数组中值为奇数的元素求和

scala

    val arr = Array(2, 4, 1, 3, 5)
    println(arr.foldLeft(0)((result, item) => result + (if (item % 2 != 0) item else 0)))

java

        Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
        Integer sumOdd = 0;
        for (Integer item : arr) {
            if (item % 2 == 1) {
                sumOdd += item;
            }
        }
        System.out.println(sumOdd);

输出
9

9 filter map collect

将数组中小于3的元素提取一个新的集合,同时将新集合中的每个元素*3

scala

    val arr = Array(2, 4, 1, 3, 5)
    arr.filter(_ < 3).map(_ * 3).foreach(println)
    //or
    arr.collect({case item : Int if item < 3 => item * 3}).foreach(println)

java

        Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
        List<Integer> result = new ArrayList<>();
        for (Integer item : arr) {
            if (item < 3) {
                result.add(item * 3);
            }
        }
        result.forEach((item) -> System.out.println(item));

输出
6
3

三 Tuple及Bean

1 定义bean class

scala

    class Dummy(val name : String, val age : Int){
      override def toString = name + "," + age
    }

java

        class Dummy {
            public Dummy(String name, Integer age) {
                this.name = name;
                this.age = age;
            }
            @Override
            public String toString() {
                return this.name + "," + this.age;
            }
            private String name = null;
            private Integer age = null;
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public Integer getAge() {
                return age;
            }
            public void setAge(Integer age) {
                this.age = age;
            }
        }

熟悉的java bean class定义,field、getter、setter、constructor、toString等;

2 Bean复杂排序

scala

    val arr1 = Array(new Dummy("a", 1), new Dummy("b", 3), new Dummy("a", 2), new Dummy("b", 1))
    //1
    println(arr1.sortBy(_.name).mkString("-"))
    //2
    println(arr1.sortBy(_.age).mkString("-"))
    //3
    println(arr1.sortWith((item1, item2) => if (item1.name.equals(item2.name)) item1.age < item2.age else item1.name.compareTo(item2.name) < 0).mkString("-"))

java

        Dummy[] arr = new Dummy[]{new Dummy("a", 1), new Dummy("b", 3), new Dummy("a", 2), new Dummy("b", 1)};
        //1
        Arrays.sort(arr, new Comparator<Dummy>(){
            @Override
            public int compare(Dummy d1, Dummy d2) {
                return d1.getName().compareTo(d2.getName());
            }
        });
        //or
        Arrays.sort(arr, ((Dummy d1, Dummy d2) -> d1.getName().compareTo(d2.getName())));
        //or
        Arrays.sort(arr, Comparator.comparing(Dummy::getName));
        System.out.println(this.mkStringInJava(arr, "-"));
        //2
        Arrays.sort(arr, Comparator.comparing(Dummy::getAge));
        System.out.println(this.mkStringInJava(arr, "-"));
        //3
        Arrays.sort(arr, ((Dummy d1, Dummy d2) -> {
            Integer result = d1.getName().compareTo(d2.getName());
            return result != 0 ? result : d1.getAge() - d2.getAge();
        }));
        System.out.println(this.mkStringInJava(arr, "-"));

输出
a,1-a,2-b,3-b,1
a,1-b,1-a,2-b,3
a,1-a,2-b,1-b,3

3 Tuple

scala

    def statistics(arr : Array[Int]) : (Int, Int, Double) = (arr.min, arr.max, arr.sum.toDouble / arr.length)
    val arr = Array(2, 4, 1, 3, 5)
    val s = statistics(arr)
    println(s._1 + ", " + s._2 + ", " + s._3)

java

    class Statistics {
        private Integer min = null;
        private Integer max = null;
        private Double avg = null;
        public Integer getMin() {
            return min;
        }
        public void setMin(Integer min) {
            this.min = min;
        }
        public Integer getMax() {
            return max;
        }
        public void setMax(Integer max) {
            this.max = max;
        }
        public Double getAvg() {
            return avg;
        }
        public void setAvg(Double avg) {
            this.avg = avg;
        }
    }
    public Statistics statistics(Integer[] arr) {
        Statistics result = new Statistics();
        Integer min = null;
        Integer max = null;
        Integer sum = 0;
        for (Integer item : arr) {
            sum += item;
            if (min == null || min > item) {
                min = item;
            }
            if (max == null || max < item) {
                max = item;
            }
        }
        result.setMin(min);
        result.setMax(max);
        result.setAvg((double)sum / arr.length);
        return result;
    }

        Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
        Statistics s = statistics(arr);
        System.out.println(s.getMin() + ", " + s.getMax() + ", " + s.getAvg());

java中方法返回多个值时通常需要借助class来实现(将多个值作为class的属性);

输出
1, 5, 3.0

4 Tuple排序

scala

    val arr = Array(("a", 1), ("b", 3), ("a", 2), ("b", 1))
    println(arr.sortBy(_._1).mkString("-"))
    println(arr.sortBy(_._2).mkString("-"))
    println(arr.sortWith((item1, item2) => if (item1._1.equals(item2._1)) item1._2 < item2._2 else item1._1.compareTo(item2._1) < 0).mkString("-"))

java中需要借助第三方库才能支持数量有限的Tuple,这里不演示了;

输出
(a,1)-(a,2)-(b,3)-(b,1)
(a,1)-(b,1)-(a,2)-(b,3)
(a,1)-(a,2)-(b,1)-(b,3)

四 IO

1 read读文件

scala

    Source.fromFile("test.log").getLines().foreach(println)

java

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(new File("test.log")));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

2 write写文件

scala

    var writer : PrintWriter = null
    try {
      writer = new PrintWriter("test.log")
      writer.write("test")
      writer.flush()
    } catch {case e : Exception => e.printStackTrace}
    finally {try {if (writer != null) writer.close()} catch {case e : Exception => e.printStackTrace}}

java

        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(new File("test.log")));
            writer.write("test");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

五 Actor 定时

akka.actor

1 Actor

scala

import akka.actor.{Actor, ActorSystem, Props}
import akka.util.Timeout
    class TestActor extends Actor {
      def receive = {
        case arg => {
          val result = "hello : " + arg
          println(result)
          Thread.sleep(3000)
          result
        }
      }
    }
    val system = ActorSystem("ActorSystem")
    val actor = system.actorOf(Props(new TestActor), "TestActor")
    actor ! "world async"
    implicit val timeout = Timeout(5, TimeUnit.SECONDS)
    import akka.pattern._
    val feature = actor ? "world async with feature"
    feature.foreach(result => println(result))

java

java.util.concurrent.LinkedBlockingQueue
java.util.concurrent.ThreadPoolExecutor
java.util.concurrent.Callable
java.util.concurrent.Future
实现效果:异步非阻塞,object接收消息放到queue中,同时内置ThreadPool不断处理消息;

2 定时

scala

    val system = ActorSystem("ActorSystem")
    import system.dispatcher
    system.scheduler.schedule(Duration.create(1000, TimeUnit. MILLISECONDS), Duration.create(1000, TimeUnit. MILLISECONDS))(
      println("hello")
    )

java

java.util.Timer
java.util.TimerTask
实现效果:定时执行task;

原文地址:https://www.cnblogs.com/barneywill/p/10159625.html

时间: 2024-10-11 11:17:59

【原创】经验分享(17)编程实践对比Java vs Scala的相关文章

运维经验分享(四)--关于 java进程管理的服务控制脚本编程思路分析

运维经验分享作为一个专题,目前共7篇文章 <运维经验分享(一)-- Linux Shell之ChatterServer服务控制脚本> <运维经验分享(二)-- Linux Shell之ChatterServer服务控制脚本二次优化> <运维经验分享(三)-- 解决Ubuntu下crontab不能正确执行Shell脚本的问题(一)> <运维经验分享(四)--关于 java进程管理的服务控制脚本编程思路分析> <运维经验分享(五)-- 改进的java进程管

【原创经验分享】JQuery(Ajax)调用WCF服务

最近在学习这个WCF,由于刚开始学 不久,发现网上的一些WCF教程都比较简单,感觉功能跟WebService没什么特别大的区别,但是看网上的介绍,就说WCF比WebService牛逼多少多少,反正我刚开始入门,就没觉得多大区别啦,这次写的东西跟WebService一样,我们写了一个WCF,那当然就是要用的,要用的话,当然不能只能在.NET平台下用了,必须跨平台呀,所以,Ajax能调用,这个基本的要求就必须要实现的了,所以,本次经验分享就是写JQuery的Ajax调用WCF的服务了.   一.新建

编程实践笔记{Java 线程 并发处理 Webservice}(转)

http://www.cnblogs.com/mingzi/archive/2009/03/09/1406694.html 1, 保证线程安全的三种方法: a, 不要跨线程访问共享变量 b, 使共享变量是final类型的 c, 将共享变量的操作加上同步 2, 一开始就将类设计成线程安全的, 比在后期重新修复它,更容易. 3, 编写多线程程序, 首先保证它是正确的, 其次再考虑性能. 4, 无状态或只读对象永远是线程安全的. 5, 不要将一个共享变量裸露在多线程环境下(无同步或不可变性保护) 6,

少儿编程发展趋势少儿编程经验分享scratch编程猫

少儿编程发展趋势 2017年7月 ×××印发人工智能发展规划,将少儿编程教育提升为国家战略2017年12月 山东省在其最新出版的小学信息技术六年级教材中,加入了编程的内容. 2018年1月 教育部公布高中新课标,编程.计算思维成必修内容.以少儿编程为代表的信息技术学科将被纳入高考,编程地位直线上升,成了高中孩子的必修科目. 2018年4月 南京教育局将编程列入南京中考特招生的范畴. 在发达国家,少儿编程教育早就已成为国家重点推动的教育学科,而我国近年来也在逐步布局发展少儿编程教育. 电子化和程序

运维经验分享(五)-- 改进的java进程管理的服务控制脚本

运维经验分享作为一个专题,目前共7篇文章 <运维经验分享(一)-- Linux Shell之ChatterServer服务控制脚本> <运维经验分享(二)-- Linux Shell之ChatterServer服务控制脚本二次优化> <运维经验分享(三)-- 解决Ubuntu下crontab不能正确执行Shell脚本的问题(一)> <运维经验分享(四)--关于 java进程管理的服务控制脚本编程思路分析> <运维经验分享(五)-- 改进的java进程管

运维经验分享(六)-- 深究crontab不能正确执行Shell脚本的问题(二)

运维经验分享作为一个专题,目前共7篇文章 <运维经验分享(一)-- Linux Shell之ChatterServer服务控制脚本> <运维经验分享(二)-- Linux Shell之ChatterServer服务控制脚本二次优化> <运维经验分享(三)-- 解决Ubuntu下crontab不能正确执行Shell脚本的问题(一)> <运维经验分享(四)--关于 java进程管理的服务控制脚本编程思路分析> <运维经验分享(五)-- 改进的java进程管

运维经验分享(七)-- Linux Shell之ChatterServer服务控制脚本第三次优化

运维经验分享作为一个专题,目前共7篇文章 <运维经验分享(一)-- Linux Shell之ChatterServer服务控制脚本> <运维经验分享(二)-- Linux Shell之ChatterServer服务控制脚本二次优化> <运维经验分享(三)-- 解决Ubuntu下crontab不能正确执行Shell脚本的问题(一)> <运维经验分享(四)--关于 java进程管理的服务控制脚本编程思路分析> <运维经验分享(五)-- 改进的java进程管

java入门经验分享——记面向对象先导课程学习感想

选择在暑期学习面向对象先导课程的初衷是为大二下学期面向对象课程做一些铺垫,接触入门java语言.在接触java的过程中,就编程语言的学习方法而言,我从刚入学时的手慌脚乱四处寻求帮助到现在慢慢养成了自己不断寻找困难解决方法的习惯,感觉自己的另一种自学能力--一种计算机工科的实践能力得到了培养,这种自学能力跟学习基础课程理论知识的感觉完全不同,这种需要在实践和动手中得到经验和知识的自学方法与以前理解现成抽象理论概念的自学方法可以说是完全不同了.作为一个偏好理论研究的理科女生,动手实践能力在此之前几乎

千回百折:百度Java研发offer斩获记和经验分享

起因 面试过程 等待offer的过程中悟道 Java面试常考知识点个人总结 过程 百度——作为国内互联网的巨头之一,最近的一些风波对其褒贬不一,但是类似事件不是第一次发生,也绝对不是最后一次,对于真的找工作的人没有丝毫影响,反而更激发了加入百度的决心,毫不夸张的说,bant(n=网易)……可谓是诸多相关专业应届学生的向往之地,本人一直有bat情节,其中偏偏独爱作为世界互联网公司排名第四,国内头三把交椅的大百度…… 而自从去年百度全面冻结hc,停止社招之后,今年陆续又缩小了实习生的招聘规模,每个部