• 朝阳消防联合快递行业开展消防安全宣传培训系列活动 2019-04-05
  • 期待已久的桃花运 竟然可以穿出来?! ——凤凰网房产广州 2019-04-05
  • 中关村雍和航星科技园,北京中关村雍和航星科技园 2019-03-22
  • 潇湘玉竹版主辛苦了! 2019-02-13
  • 端午新经济体验无处不在 “指尖端午”玩出新花样 2019-02-13
  • 工信部:鼓励婴幼儿配方乳企质量安全追溯体系建设 2018-12-30
  • "背景 JDK 11 已经快要来了,所以 JDK 的新特征还是要及时学习的。 先从 JDK 8 的特征来入手吧。 本文先记录一下 lambda 表达式的学习。 另外,在 ClickHouse 的学习中,发现 ClickHouse 也支持了 lambda 表达式做为 SQL 的一部分。 所以 lambda 表达式已经是常识 .."

    java8 lambda 表达式学习

    本贴最后更新于 297 天前,其中的信息可能已经东海扬尘

    背景

    天中图库好运财新福 www.zpvv.net JDK 11 已经快要来了,所以 JDK 的新特征还是要及时学习的。

    先从 JDK 8 的特征来入手吧。

    本文先记录一下 lambda 表达式的学习。

    另外,在 ClickHouse 的学习中,发现 ClickHouse 也支持了 lambda 表达式做为 SQL 的一部分。

    所以 lambda 表达式已经是常识了。

    lambda 表达式例子

    创建线程

    public class MainLambda {
    	public static void main(String[] args) {
    		Thread thread = new Thread(() -> System.out.println("Hello world!"));
    		thread.start();
    	}
    }
    

    输出

    Hello world!
    

    排序

    public class MainLambda {
    	public static void main(String[] args) {
    		List<String> list = Arrays.asList(new String[] { "b", "c", "a" });
    		Collections.sort(list, (s1, s2) -> s1.www.zpvv.netpareTo(s2));
    		System.out.println(list);
    	}
    }
    

    输出

    [a, b, c]
    

    转换成大写

    public class MainLambda {
    	public static void main(String[] args) {
    		List<String> list = Arrays.asList(new String[] { "b", "c", "a" });
    		List<String> newlist = list.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
    		System.out.println(newlist);
    	}
    }
    

    输出

    [B, C, A]
    

    遍历每个元素

    import java.util.Arrays;
    import java.util.List;
    
    public class MainLambda {
    	public static void main(String[] args) {
    		List<String> list = Arrays.asList(new String[] { "b", "c", "a" });
    		list.stream().forEach(s -> System.out.println(s.toUpperCase()));
    	}
    }
    

    输出

    B
    C
    A
    

    lambda 表达式语法

    一般语法

    (Type1 param1, Type2 param2, ..., TypeN paramN) -> {
      statment1;
      statment2;
      //.............
      return statmentM;
    }
    

    单参数语法

    可以省略前面的小括号

    param1 -> {
      statment1;
      statment2;
      //.............
      return statmentM;
    }
    

    单语句语法

    可以省略后面的大括号, 以及 return 语句。

    param1 -> statment
    

    方法引用语法

    Class or instance :: method
    

    变量作用域

    外部变量在 lambda 表达式引用时,jdk 8 编译器会隐式做为 final 来处理

    stream

    上面的转换成小写就是一个 stream 的例子。

    执行概况

    生成

    collection.stream()

    转换

    汇聚 (Reduce)

    collect 方法

    示例

    public class MainLambda {
    	public static void main(String[] args) {
    		List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
    		List<Integer> numsWithoutNull = nums.stream()
    				.filter(num -> num != null)
    				.collect(
    						() -> new ArrayList<Integer>(),
    						(list, item) -> list.add(item), 
    						(list1, list2) -> list1.addAll(list2)
    				);
    		System.out.println(numsWithoutNull);
    	}
    }
    

    结果

    [1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    其中 collect 有三个参数

    1. supplier: 生成一个新的实例
    2. accumulator(对象,元素): 把元素加入对象中
    3. www.zpvv.netbiner(对象, 对象): 合并两个对象

    此外,JDK 提供了 Collector 接口,方便来写 collect。这里不多写了。

    另外,JDK 预定义了常用的 Collector 接口实现,如 Collectors.toList() 之类。

    因此,上面的例子可以写成

    public class MainLambda {
    	public static void main(String[] args) {
    		List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
    		List<Integer> numsWithoutNull = nums.stream()
    				.filter(num -> num != null)
    				.collect(Collectors.toList());
    		System.out.println(numsWithoutNull);
    	}
    }
    
    

    结果

    [1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    reduce 方法

    示例:求和元素

    import www.zpvv.net.google.www.zpvv.netmon.collect.Lists;
    
    public class MainLambda {
    	public static void main(String[] args) {
    		List<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    		int value = ints.stream()
    				.reduce((sum, item) -> sum + item)
    				.get();
    		System.out.println("ints sum is:" + value);
    	}
    }
    

    结果

    ints sum is:55
    

    其中 reduce 的两个参数,第一个参数 sum 是上一次 reduce 的返回值,第二个参数是本次的元素。所以实际执行过程是: ((( (1+2) + 3 )+ 4) + 5 )

    也可以提供一个循环的初始值,如 -1

    import java.util.List;
    
    import www.zpvv.net.google.www.zpvv.netmon.collect.Lists;
    
    public class MainLambda {
    	public static void main(String[] args) {
    		List<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    		int value = ints.stream()
    				.reduce(-1, (sum, item) -> sum + item);
    		System.out.println("ints sum is:" + value);
    	}
    }
    
    

    结果

    ints sum is:54
    

    count

    示例

    import java.util.List;
    
    import www.zpvv.net.google.www.zpvv.netmon.collect.Lists;
    
    public class MainLambda {
    	public static void main(String[] args) {
    		List<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    		long value = ints.stream().count();
    		System.out.println("ints sum is:" + value);
    	}
    }
    

    结果

    ints sum is:10
    

    其它

    执行示例

    import java.util.List;
    
    import www.zpvv.net.google.www.zpvv.netmon.collect.Lists;
    
    public class MainLambda {
    	public static void main(String[] args) {
    		List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
    		int sum = nums.stream()
    				.filter(num -> num != null)
    				.distinct()
    				.mapToInt(num -> num * 2)
    				.skip(2)
    				.limit(4)
    				.peek(System.out::println)
    				.sum();
    		System.out.println("sum is:" + sum);
    	}
    }
    
    

    结果: 首先 skip 掉了前 2 个元素,又 limit 了 4 个元素,所以最后剩下了 6,8,10,12 共 4 个元素,其和为 36。

    6
    8
    10
    12
    sum is:36
    

    并行执行

    通过parallelStream,来实现并行执行,默认为 8 个并发。

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.function.Consumer;
    import java.util.function.Function;
    
    import org.apache.http.client.fluent.Request;
    import org.apache.http.client.fluent.Response;
    
    public class Java8AsyncRequest {
    	public static void main(String[] args) {
    		List<String> emitters = new ArrayList<String>();
    		for (int i = 0; i != 1000; ++i) {
    			emitters.add("//www.abeffect.com/" + i);
    
    		}
    
    		emitters.parallelStream().map(new Function<String, Response>() {
    			@Override
    			public Response apply(String s) {
    				try {
    					System.out.println(Thread.currentThread() + ":" + s);
    					Thread.sleep(5000L);
    					return Request.Get(s).execute();
    				} catch (IOException | InterruptedException e) {
    					e.printStackTrace();
    					return null;
    				}
    			}
    		}).forEach(new Consumer<Response>() {
    
    			@Override
    			public void accept(Response response) {
    				try {
    					System.out.println(response.returnResponse().getStatusLine().getStatusCode());
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		});
    	}
    }
    
    

    参考

    • B3log

      B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:Pipe、Solo、Sym、 Wide 等,欢迎大家加入,贡献开源。

      2430 引用 ? 3805 回帖 ? 623 关注
    • Java

      Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

      2169 引用 ? 7359 回帖 ? 1040 关注
    感谢    关注    收藏    赞同    反对    举报    分享
    15 回帖    
    请输入回帖内容...
    • gitors ?      

      我不知道为什么,现在我同事还在拒绝 Java 8 ,我写的 简单的 list foreach, 我看到他看我代码的时候给我改成 for(){

      } 了。。。

      2 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • 88250 ?            

      不学习会被社会抛弃的,只能祝他好运了。

      感谢    赞同    反对    举报    分享       评论    回复
    • scmod ?            

      可能他用到了 index~? 滑稽 ~

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • gitors ?            

      是我写的代码啊。没用 index ,就是 遍历一下而已。

      感谢    赞同    反对    举报    分享       评论    回复
    • gitors ?      

      今天叫我安装了代码统计插件,阶段性统计代码行数。。。难道是以代码行数评绩效的?我都不敢重构以前都代码了

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • flowaters ?            

      重构以前代码。。。这个还是很有挑战性的。

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • gitors ?            

      我所说的重构就是简单的修改,看哪里以前写的不好的,修改一下,要么是使代码简洁,要么是进行抽取封装,基本大的结构也是不敢改的

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • k1ncccc ?      

      ??

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • vinasis ?      

      半条命的 logo

      感谢    赞同    反对    举报    分享       评论    回复
    • dkzwm ?      

      ??

      感谢    赞同    反对    举报    分享       评论    回复
    • 111wsedfcgvb ?            

      啥表情哈哈

      感谢    赞同    反对    举报    分享       评论    回复
    • Peiel ?            

      个人理解,无论大小,只要重构代码,就必须跑测试用例,否则很容易出问题。

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • gitors ?            

      单元测试不是打包必跑的吗?

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • TheNow ?            

      可以跳过啊 mvn package -Dmaven.test.skip=true 跳过单元测试.
      你的问题我理解的对吗?

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • gitors ?            

      是这样的,以前我们是持续集成,本地不跑单元测试,集成服务器还是会跑的,所以我们打包都不会跳过单元测试,否则可能导致集成失败

      感谢    赞同    反对    举报    分享       评论    回复
    请输入回帖内容...
  • 朝阳消防联合快递行业开展消防安全宣传培训系列活动 2019-04-05
  • 期待已久的桃花运 竟然可以穿出来?! ——凤凰网房产广州 2019-04-05
  • 中关村雍和航星科技园,北京中关村雍和航星科技园 2019-03-22
  • 潇湘玉竹版主辛苦了! 2019-02-13
  • 端午新经济体验无处不在 “指尖端午”玩出新花样 2019-02-13
  • 工信部:鼓励婴幼儿配方乳企质量安全追溯体系建设 2018-12-30