【原创】大叔经验分享(17)编程实践对比Java vs Scala
scala
官方地址 https://www.scala-lang.org/
本文尽可能包含了一些主要的java和scala在编程实践时的显著差异,展现scala的代码的简洁优雅;scala通吃<面向对象编程Object Oriented Programming>和<函数式编程Functional Programming>,有很多开源组件都用scala开发(比如spark、kafka等),虽然java从8开始支持lambda表达式,有些方面已经接近scala,但是...
直接看代码对比:
一 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)
//or
Array.range(0, 10, 2).foreach(println)
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)
//
println(arr.sorted.mkString(","))
//
println(arr.sorted.reverse.mkString(","))
//
println(arr.sortWith((v1 : Int, v2 : Int) => v2 < v1).mkString(","))
java
Integer[] arr = new Integer[]{2, 4, 1, 3, 5};
//
Arrays.sort(arr);
for (Integer item : arr) {
System.out.println(item);
}
//or
Arrays.asList(arr).forEach((v) -> System.out.println(v));
//
for (int i = arr.length - 1; i >= 0; i--) {
System.out.println(arr[i]);
}
//
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))
//
println(arr1.sortBy(_.name).mkString("-"))
//
println(arr1.sortBy(_.age).mkString("-"))
//
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)};
//
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, "-"));
//
Arrays.sort(arr, Comparator.comparing(Dummy::getAge));
System.out.println(this.mkStringInJava(arr, "-"));
//
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;
六 continue/break
scala
import scala.util.control.Breaks._ breakable {
...
break
...
}
java 原生支持
【原创】大叔经验分享(17)编程实践对比Java vs Scala的更多相关文章
- 【原创】经验分享:一个小小emoji尽然牵扯出来这么多东西?
前言 之前也分享过很多工作中踩坑的经验: 一个线上问题的思考:Eureka注册中心集群如何实现客户端请求负载及故障转移? [原创]经验分享:一个Content-Length引发的血案(almost.. ...
- 【原创】大叔经验分享(7)创建hive表时格式如何选择
常用格式 textfile 需要定义分隔符,占用空间大,读写效率最低,非常容易发生冲突(分隔符)的一种格式,基本上只有需要导入数据的时候才会使用,比如导入csv文件: ROW FORMAT DELIM ...
- 【原创】大叔经验分享(43)logstash设置jdbc_default_timezone后报错
logstash6.6.0-6.6.2版本使用jdbc input plugin时如果设置了jdbc_default_timezone,会报错: { 2012 rufus-scheduler inte ...
- 【原创】大叔经验分享(35)lzo格式支持
建表语句 CREATE EXTERNAL TABLE `my_lzo_table`(`something` string)ROW FORMAT DELIMITED FIELDS TERMINATED ...
- 【原创】大叔经验分享(90)linux服务器iowait和负载很高
# top top - 21:21:51 up 207 days, 1:30, 5 users, load average: 0.90, 0.79, 1.62 Tasks: 249 total, 1 ...
- 【原创】大叔经验分享(63)kudu vs parquet
一 对比 存储空间对比: 查询性能对比: 二 设计方案 将数据拆分为:历史数据(hdfs+parquet+snappy)+ 近期数据(kudu),可以兼具各种优点: 1)整体低于10%的磁盘占用: 2 ...
- 【原创】大叔经验分享(51)docker报错Exited (137)
docker container启动失败,报错:Exited (137) *** ago,比如 Exited (137) 16 seconds ago 这时通过docker logs查不到任何日志,从 ...
- 【原创】大叔经验分享(50)hue访问mysql(librdbms)
cloudera manager安装hue后想开启访问mysql(librdbms)需要在这里配置(hue_safety_valve.ini) 添加配置如下 [librdbms] # The RDBM ...
- 【原创】大叔经验分享(49)hue访问hdfs报错/hue访问oozie editor页面卡住
hue中使用hue用户(hue admin)访问hdfs报错: Cannot access: /. Note: you are a Hue admin but not a HDFS superuser ...
随机推荐
- Ansible第一章:基础认识--小白博客
ansible Ansible:Ansible的核心程序Host Lnventory:记录了每一个由Ansible管理的主机信息,信息包括ssh端口,root帐号密码,ip地址等等.可以通过file来 ...
- openstack搭建之-neutron配置(11)
一.base节点设置 mysql -u root -proot CREATE DATABASE neutron; GRANT ALL PRIVILEGES ON neutron.* TO 'neutr ...
- Node.js的事件处理机制
1. 为什么Node.js是单线程执行的 因为从JavaScript设计之初,JavaScript是用户与浏览器交互的,主要处理DOM: 这样决定了JavaScript是单线程执行,否则会出现问题:例 ...
- Python——Django-form表单提交
一.提交的注意事项 1. form不是from,所有获取用户输入的标签都应该放在form里面, input并且必须要有name属性 2. action属性控制往哪儿提交,method一般都设置成pos ...
- poj-1807(最大流)
题意:给你n个插座,m个电器,每个电器有插头,还有k个插头转换器,可以把插座A变成插座B,转换器可以连续使用,比如A转换B,再从B转换C 解题思路:这道题就是题意麻烦,看懂了就很简单,首先建一个汇点和 ...
- [模板] 数位dp
数位dp 简介 数位dp指满足特定性质的数的计数, 如求 \([l, r]\) 区间内不含 \(2\) 的数的个数. 一般来说, 数位dp利用dfs解决, 有时状态数较多, 需要hash表优化. 模板 ...
- 【NLP】Conditional Language Models
Language Model estimates the probs that the sequences of words can be a sentence said by a human. Tr ...
- mysql数据去重并排序使用distinct 和 order by 的问题
比如直接使用: SELECT distinct mobileFROM table_aWHERE code = 123ORDER BY a_ime desc 在本地mysql数据库没有错,在线上的数据库 ...
- 使用item来封装数据:
一.item和field类: 1.使用Item类: 创建了类Bookitem,然后就可以使用: 2.item_pipeline: 我们可以使用item_pipeline对爬取的数据进行处理. 步骤: ...
- pymongo 使用方法(增删改查)
#!/usr/bin/env python # -*- coding:utf-8 -*- """ MongoDB存储 在这里我们来看一下Python3下MongoDB的存 ...