1.增加JDK1.8中的Lambda、Stream和日期的示例代码
This commit is contained in:
parent
51450ef543
commit
5e3d7d0e16
@ -1,65 +1,165 @@
|
||||
package com.pancm.jdk8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.pancm.pojo.User;
|
||||
|
||||
/**
|
||||
* @Title: LambdaTest
|
||||
* @Description: 拉姆达表达式
|
||||
* @Version:1.0.0
|
||||
* @author pancm
|
||||
* @date 2018年8月28日
|
||||
*/
|
||||
public class LambdaTest {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
test1();
|
||||
test2();
|
||||
}
|
||||
|
||||
private static void test1(){
|
||||
Map<String , String> map = new HashMap<>();
|
||||
map.put("a","a");
|
||||
map.put("b","b");
|
||||
map.put("c","c");
|
||||
map.put("d","d");
|
||||
map.put("e","e");
|
||||
map.put("f","f");
|
||||
|
||||
map.forEach((k,v)->{
|
||||
System.out.println("k="+k+",v="+v);
|
||||
});
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("aaa");
|
||||
list.add("bbbbb");
|
||||
list.add("ccccccc");
|
||||
list.add("dddd");
|
||||
list.forEach(v->{
|
||||
System.out.println(v);
|
||||
});
|
||||
}
|
||||
|
||||
private static void test2(){
|
||||
List<User> list = new ArrayList<User>();
|
||||
List<User> list2 = new ArrayList<User>();
|
||||
list.add(new User(1, "张三"));
|
||||
list.add(new User(2, "李四"));
|
||||
list.add(new User(3, "王五"));
|
||||
list.add(new User(4, "赵六"));
|
||||
System.out.println("list:"+list);
|
||||
list.forEach(v->{
|
||||
if(v.getId()>2){
|
||||
list2.add(v);
|
||||
}
|
||||
});
|
||||
System.out.println("list2:"+list2);
|
||||
}
|
||||
}
|
||||
package com.pancm.jdk8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
/**
|
||||
* @Title: lambdaTest
|
||||
* @Description: 拉姆达表达式
|
||||
*
|
||||
* @Version:1.0.0
|
||||
* @author pancm
|
||||
* @date 2018年8月28日
|
||||
*/
|
||||
public class LambdaTest {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
test1();
|
||||
test2();
|
||||
}
|
||||
|
||||
private static void test1() {
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("a", "a");
|
||||
map.put("b", "b");
|
||||
map.put("c", "c");
|
||||
map.put("d", "d");
|
||||
|
||||
System.out.println("map普通方式遍历:");
|
||||
for (String key : map.keySet()) {
|
||||
System.out.println("k=" + key + ",v=" + map.get(key));
|
||||
}
|
||||
|
||||
System.out.println("map拉姆达表达式遍历:");
|
||||
map.forEach((k, v) -> {
|
||||
System.out.println("k=" + k + ",v=" + v);
|
||||
});
|
||||
|
||||
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("a");
|
||||
list.add("bb");
|
||||
list.add("ccc");
|
||||
list.add("dddd");
|
||||
System.out.println("list拉姆达表达式遍历:");
|
||||
list.forEach(v -> {
|
||||
System.out.println(v);
|
||||
});
|
||||
System.out.println("list双冒号运算符遍历:");
|
||||
list.forEach(System.out::println);
|
||||
|
||||
}
|
||||
|
||||
private static void test2() {
|
||||
List<User> list = new ArrayList<User>();
|
||||
List<User> list2 = new ArrayList<User>();
|
||||
list.add(new User(1, "张三"));
|
||||
list.add(new User(2, "李四"));
|
||||
list.add(new User(3, "王五"));
|
||||
list.add(new User(4, "赵六"));
|
||||
System.out.println("list:" + list);
|
||||
list.forEach(v -> {
|
||||
if (v.getId() > 2) {
|
||||
list2.add(v);
|
||||
}
|
||||
});
|
||||
System.out.println("list2:" + list2);
|
||||
}
|
||||
|
||||
//使用普通的方式创建
|
||||
Runnable r1 = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("普通方式创建!");
|
||||
}
|
||||
};
|
||||
|
||||
//使用拉姆达方式创建
|
||||
Runnable r2 = ()-> System.out.println("拉姆达方式创建!");
|
||||
|
||||
|
||||
}
|
||||
|
||||
class User {
|
||||
|
||||
/** 编号 */
|
||||
private int id;
|
||||
/** 姓名 */
|
||||
private String name;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
*
|
||||
* @param id 编号
|
||||
* @param name 姓名
|
||||
*/
|
||||
public User(int id, String name) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编号
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置编号
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取姓名
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName() {
|
||||
System.out.println("姓名:" + name);
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置姓名
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Map toMap() {
|
||||
return JSON.parseObject(toString(), HashMap.class);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{\"id\":\"" + id + "\",\"name\":\"" + name + "\"}";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
228
src/main/java/com/pancm/jdk8/LocalDateTimeTest.java
Normal file
228
src/main/java/com/pancm/jdk8/LocalDateTimeTest.java
Normal file
@ -0,0 +1,228 @@
|
||||
package com.pancm.jdk8;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Month;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* @Title: timeTest
|
||||
* @Description:
|
||||
* 时间测试
|
||||
* @Version:1.0.0
|
||||
* @author pancm
|
||||
* @date 2018年6月21日
|
||||
*/
|
||||
public class LocalDateTimeTest {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
/*
|
||||
|
||||
新版API中java.time包里的一些关键类:
|
||||
|
||||
Instant:瞬时实例。
|
||||
LocalDate:本地日期,不包含具体时间 例如:2014-01-14 可以用来记录生日、纪念日、加盟日等。
|
||||
LocalTime:本地时间,不包含日期。
|
||||
LocalDateTime:组合了日期和时间,但不包含时差和时区信息。
|
||||
ZonedDateTime:最完整的日期时间,包含时区和相对UTC或格林威治的时差。
|
||||
|
||||
|
||||
Java 8日期时间API 使用说明:
|
||||
|
||||
1)提供了javax.time.ZoneId 获取时区。
|
||||
|
||||
2)提供了LocalDate和LocalTime类。
|
||||
|
||||
3)Java 8 的所有日期和时间API都是不可变类并且线程安全,而现有的Date和Calendar API中的java.util.Date和SimpleDateFormat是非线程安全的。
|
||||
|
||||
4)主包是 java.time,包含了表示日期、时间、时间间隔的一些类。里面有两个子包java.time.format用于格式化, java.time.temporal用于更底层的操作。
|
||||
|
||||
5)时区代表了地球上某个区域内普遍使用的标准时间。每个时区都有一个代号,格式通常由区域/城市构成(Asia/Tokyo),在加上与格林威治或 UTC的时差。例如:东京的时差是+09:00。
|
||||
|
||||
6)OffsetDateTime类实际上组合了LocalDateTime类和ZoneOffset类。用来表示包含和格林威治或UTC时差的完整日期(年、月、日)和时间(时、分、秒、纳秒)信息。
|
||||
|
||||
7)DateTimeFormatter 类用来格式化和解析时间。与SimpleDateFormat不同,这个类不可变并且线程安全,需要时可以给静态常量赋值。 DateTimeFormatter类提供了大量的内置格式化工具,同时也允许你自定义。在转换方面也提供了parse()将字符串解析成日期,如果解析出错会抛出DateTimeParseException。DateTimeFormatter类同时还有format()用来格式化日期,如果出错会抛出DateTimeException异常。
|
||||
|
||||
8)再补充一点,日期格式“MMM d yyyy”和“MMM dd yyyy”有一些微妙的不同,第一个格式可以解析“Jan 2 2014”和“Jan 14 2014”,而第二个在解析“Jan 2 2014”就会抛异常,因为第二个格式里要求日必须是两位的。如果想修正,你必须在日期只有个位数时在前面补零,就是说“Jan 2 2014”应该写成 “Jan 02 2014”。
|
||||
|
||||
*/
|
||||
|
||||
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static void test1(){
|
||||
|
||||
/*
|
||||
* 获取当前时间
|
||||
*/
|
||||
//本地日期,不包括时分秒
|
||||
LocalDate nowDate = LocalDate.now();
|
||||
//本地日期,包括时分秒
|
||||
LocalDateTime nowDateTime = LocalDateTime.now();
|
||||
System.out.println("当前时间:"+nowDate);
|
||||
System.out.println("当前时间:"+nowDateTime);
|
||||
// 当前时间:2018-12-19
|
||||
// 当前时间:2018-12-19T15:24:35.822
|
||||
|
||||
/*
|
||||
* 格式化时间
|
||||
*/
|
||||
LocalDate ld=LocalDate.parse("2017-11-17");
|
||||
LocalDate ld2=LocalDate.parse("2018-01-05");
|
||||
|
||||
/**
|
||||
* 创建指定日期
|
||||
*/
|
||||
LocalDate ld3=LocalDate.of(2017, Month.NOVEMBER, 17);
|
||||
LocalDate ld4=LocalDate.of(2018, 02, 11);
|
||||
//jdk1.8的类,用于比较时间
|
||||
//可以得到相差年、月、日
|
||||
Period p=Period.between(ld, ld2);
|
||||
System.out.println("相差年: "+p.getYears()+" 相差月 :"+p.getMonths() +" 相差天:"+p.getDays());
|
||||
// 相差年: 0 相差月 :1 相差天:19
|
||||
|
||||
System.out.println("增加2个月: "+ld.plusMonths(2));
|
||||
Period p2=Period.between(ld3, ld4);
|
||||
System.out.println("相差年: "+p2.getYears()+" 相差月 :"+p2.getMonths() +" 相差天:"+p2.getDays()+"--"+p2.toTotalMonths());
|
||||
//相差年: 0 相差月 :2 相差天:25
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间测试
|
||||
*/
|
||||
private static void test2(){
|
||||
// String time="2018-06-29 09:19:45.498";
|
||||
String time2="2018-01-04T09:19:29.499";
|
||||
//格式化时间
|
||||
LocalDateTime ldt2=LocalDateTime.parse(time2);
|
||||
//获取当前的时间,包括毫秒
|
||||
LocalDateTime ldt = LocalDateTime.now();
|
||||
System.out.println("当前年:"+ldt.getYear()); //2018
|
||||
System.out.println("当前年份天数:"+ldt.getDayOfYear());//172
|
||||
System.out.println("当前月:"+ldt.getMonthValue());
|
||||
System.out.println("当前时:"+ldt.getHour());
|
||||
System.out.println("当前分:"+ldt.getMinute());
|
||||
System.out.println("当前时间:"+ldt.toString());
|
||||
// 当前年:2018
|
||||
// 当前年份天数:353
|
||||
// 当前月:12
|
||||
// 当前时:15
|
||||
// 当前分:24
|
||||
// 当前时间:2018-12-19T15:24:35.833
|
||||
|
||||
|
||||
System.out.println("格式化时间: "+ ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
|
||||
//格式化时间:2018-12-19 15:37:47.119
|
||||
|
||||
System.out.println("后5天时间:"+ldt.plusDays(5));
|
||||
System.out.println("前5天时间并格式化:"+ldt.minusDays(5).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); //2018-06-16
|
||||
System.out.println("前一个月的时间:"+ldt2.minusMonths(1).format(DateTimeFormatter.ofPattern("yyyyMM"))); //2018-06-16
|
||||
System.out.println("后一个月的时间:"+ldt2.plusMonths(1)); //2018-06-16
|
||||
System.out.println("指定2099年的当前时间:"+ldt.withYear(2099)); //2099-06-21T15:07:39.506
|
||||
// 后5天时间:2018-12-24T15:50:37.508
|
||||
// 前5天时间并格式化:2018-12-14
|
||||
// 前一个月的时间:201712
|
||||
// 后一个月的时间:2018-02-04T09:19:29.499
|
||||
// 指定2099年的当前时间:2099-12-19T15:50:37.508
|
||||
|
||||
System.out.println("得到的时间:"+ldt2.toString());
|
||||
System.out.println("格式化时间:"+ldt2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
通过 Clock时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。
|
||||
*/
|
||||
Clock clock = Clock.systemUTC();
|
||||
System.out.println("当前时间戳 : " + clock.millis());
|
||||
Clock clock2 = Clock.system(ZoneId.of("Asia/Shanghai"));
|
||||
System.out.println("亚洲上海此时的时间戳:"+clock2.millis());
|
||||
Clock clock3 = Clock.system(ZoneId.of("America/New_York"));
|
||||
System.out.println("美国纽约此时的时间戳:"+clock3.millis());
|
||||
// 当前时间戳 : 1545209277657
|
||||
// 亚洲上海此时的时间戳:1545209277657
|
||||
// 美国纽约此时的时间戳:1545209277658
|
||||
|
||||
/*
|
||||
* 时区计算
|
||||
*/
|
||||
ZoneId zoneId= ZoneId.of("America/New_York");
|
||||
ZonedDateTime dateTime=ZonedDateTime.now(zoneId);
|
||||
System.out.println("美国纽约此时的时间 : " + dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
|
||||
System.out.println("美国纽约此时的时间 和时区: " + dateTime);
|
||||
// 美国纽约此时的时间 : 2018-12-19 03:52:22.494
|
||||
// 美国纽约此时的时间 和时区: 2018-12-19T03:52:22.494-05:00[America/New_York]
|
||||
|
||||
/**
|
||||
*
|
||||
* 时间比较
|
||||
*/
|
||||
LocalDateTime ldt4 = LocalDateTime.now();
|
||||
LocalDateTime ldt5 = ldt4.plusMinutes(10);
|
||||
System.out.println("当前时间是否大于:"+ldt4.isAfter(ldt5));
|
||||
System.out.println("当前时间是否小于"+ldt4.isBefore(ldt5));
|
||||
// false
|
||||
// true
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static void test3(){
|
||||
/*
|
||||
* Duration 这个类以秒和纳秒为单位建模时间的数量或数量
|
||||
*/
|
||||
Instant inst1 = Instant.now();
|
||||
System.out.println("当前时间戳: " + inst1);
|
||||
Instant inst2 = inst1.plus(Duration.ofSeconds(10));
|
||||
System.out.println("增加之后的时间 : " + inst2);
|
||||
System.out.println("相差毫秒 : " + Duration.between(inst1, inst2).toMillis());
|
||||
System.out.println("相毫秒 : " + Duration.between(inst1, inst2).getSeconds());
|
||||
// 当前时间戳 : 2018-12-19T08:14:21.675Z
|
||||
// 增加之后的时间 : 2018-12-19T08:14:31.675Z
|
||||
// 相差毫秒 : 10000
|
||||
// 相毫秒 : 10
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 单个时间单位内测量一段时间
|
||||
*/
|
||||
private static void test4(){
|
||||
/*
|
||||
* ChronoUnit 日期周期单位的标准集合。
|
||||
*/
|
||||
LocalDate startDate = LocalDate.of(2017, 11, 17);
|
||||
LocalDate endDate = LocalDate.of(2018, 01, 05);
|
||||
System.out.println("相差月份:"+ChronoUnit.MONTHS.between(startDate, endDate));
|
||||
System.out.println("两月之间的相差的天数 : " + ChronoUnit.DAYS.between(startDate, endDate));
|
||||
// 相差月份:1
|
||||
// 两天之间的差在天数 : 49
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,423 +1,558 @@
|
||||
package com.pancm.jdk8;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.pancm.pojo.User;
|
||||
|
||||
/**
|
||||
* @Title: StreamTest
|
||||
* @Description: Stream测试用例 流的操作类型分为两种:
|
||||
*
|
||||
* Intermediate:一个流可以后面跟随零个或多个 intermediate
|
||||
* 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。
|
||||
* 这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。 Terminal:一个流只能有一个
|
||||
* terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。 所以这必定是流的最后一个操作。 Terminal
|
||||
* 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
|
||||
* @Version:1.0.0
|
||||
* @author pancm
|
||||
* @date 2018年9月3日
|
||||
*/
|
||||
public class StreamTest {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
|
||||
/*
|
||||
* Stream 的特性可以归纳为:
|
||||
不是数据结构
|
||||
它没有内部存储,它只是用操作管道从 source(数据结构、数组、generator function、IO channel)抓取数据。
|
||||
它也绝不修改自己所封装的底层数据结构的数据。例如 Stream 的 filter 操作会产生一个不包含被过滤元素的新 Stream,而不是从 source 删除那些元素。
|
||||
所有 Stream 的操作必须以 lambda 表达式为参数
|
||||
不支持索引访问
|
||||
你可以请求第一个元素,但无法请求第二个,第三个,或最后一个。不过请参阅下一项。
|
||||
很容易生成数组或者 List
|
||||
惰性化
|
||||
很多 Stream 操作是向后延迟的,一直到它弄清楚了最后需要多少数据才会开始。
|
||||
Intermediate 操作永远是惰性化的。
|
||||
并行能力
|
||||
当一个 Stream 是并行化的,就不需要再写多线程代码,所有对它的操作会自动并行进行的。
|
||||
可以是无限的
|
||||
集合有固定大小,Stream 则不必。limit(n) 和 findFirst() 这类的 short-circuiting 操作可以对无限的 Stream 进行运算并很快完成。
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单实用
|
||||
*/
|
||||
private static void test1() {
|
||||
/*
|
||||
* 普通的方式过滤
|
||||
*/
|
||||
List<String> list = Arrays.asList("张三", "李四", "王五");
|
||||
System.out.println("过滤之前:" + list);
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String str : list) {
|
||||
if (!"李四".equals(str)) {
|
||||
result.add(str);
|
||||
}
|
||||
}
|
||||
System.out.println("过滤之后:" + result);
|
||||
|
||||
/*
|
||||
* stream 过滤
|
||||
*/
|
||||
List<String> result2 = list.stream().filter(str -> !"李四".equals(str)).collect(Collectors.toList());
|
||||
System.out.println("stream 过滤之后:" + result2);
|
||||
// 另一种方式输出
|
||||
result2.forEach(System.out::println);
|
||||
|
||||
// 使用stream.filter ()过滤一列表,并.findAny().orElse
|
||||
// 遍历该list,查询数据,如果查不到,就返回 找不到!
|
||||
String result3 = list.stream().filter(str -> "李四".equals(str)).findAny().orElse("找不到!");
|
||||
String result4 = list.stream().filter(str -> "李二".equals(str)).findAny().orElse("找不到!");
|
||||
|
||||
System.out.println("stream 过滤之后 2:" + result3);
|
||||
System.out.println("stream 过滤之后 3:" + result4);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本使用
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
|
||||
private static void test2() {
|
||||
|
||||
/*
|
||||
* 构造流的几种方式
|
||||
*/
|
||||
Stream stream = Stream.of("a", "b", "c");
|
||||
String[] strArray = new String[] { "a", "b", "c" };
|
||||
stream = Stream.of(strArray);
|
||||
stream = Arrays.stream(strArray);
|
||||
List<String> list = Arrays.asList(strArray);
|
||||
stream = list.stream();
|
||||
|
||||
/*
|
||||
* 流之间的相互转化 一个 Stream 只可以使用一次,这段代码为了简洁而重复使用了数次,因此会抛出异常
|
||||
*/
|
||||
try {
|
||||
Stream<String> stream2 = Stream.of("a", "b", "c");
|
||||
// 转换成 Array
|
||||
String[] strArray1 = stream2.toArray(String[]::new);
|
||||
|
||||
// 转换成 Collection
|
||||
List<String> list1 = stream2.collect(Collectors.toList());
|
||||
List<String> list2 = stream2.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
Set set1 = stream2.collect(Collectors.toSet());
|
||||
Stack stack1 = stream2.collect(Collectors.toCollection(Stack::new));
|
||||
|
||||
// 转换成 String
|
||||
String str = stream.collect(Collectors.joining()).toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/*
|
||||
* 汇总操作
|
||||
*/
|
||||
List<User> lists = new ArrayList<User>();
|
||||
lists.add(new User(6, "张三"));
|
||||
lists.add(new User(2, "李四"));
|
||||
lists.add(new User(3, "王五"));
|
||||
lists.add(new User(1, "张三"));
|
||||
// 计算这个list中出现 "张三" id的值
|
||||
int sum = lists.stream().filter(u -> "张三".equals(u.getName())).mapToInt(u -> u.getId()).sum();
|
||||
|
||||
System.out.println("计算结果:" + sum); // 7
|
||||
|
||||
/*
|
||||
* 数值类型的流 包括IntStream, LongStream和DoubleStream
|
||||
*/
|
||||
System.out.println("遍历输出该数组的数据:");
|
||||
IntStream.of(new int[] { 1, 2, 3, 4 }).forEach(System.out::println);
|
||||
System.out.println("查询范围在 2-3(2<=i<3)之间的数据:");
|
||||
IntStream.range(2, 3).forEach(System.out::println);
|
||||
System.out.println("查询范围在2-3(2<=i<=3)之间的数据:");
|
||||
IntStream.rangeClosed(2, 3).forEach(System.out::println);
|
||||
|
||||
/* stream中的 map使用 */
|
||||
|
||||
/*
|
||||
* 转换大写
|
||||
*/
|
||||
List<String> list3 = Arrays.asList("zhangSan", "liSi", "wangWu");
|
||||
System.out.println("转换之前的数据:" + list3);// 转换之前的数据:[zhangSan, liSi,
|
||||
// wangWu]
|
||||
List<String> list4 = list3.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
System.out.println("转换之后的数据:" + list4); // 转换之后的数据:[ZHANGSAN, LISI,
|
||||
// WANGWU]
|
||||
|
||||
/*
|
||||
* 转换数据类型
|
||||
*/
|
||||
List<String> list31 = Arrays.asList("1", "2", "3");
|
||||
System.out.println("转换之前的数据:" + list31);// 转换之前的数据:[1, 2, 3]
|
||||
List<Integer> list41 = list31.stream().map(Integer::valueOf).collect(Collectors.toList());
|
||||
System.out.println("转换之后的数据:" + list41); // [1, 2, 3]
|
||||
|
||||
|
||||
/*
|
||||
* 转换数据类型
|
||||
* 对象转map
|
||||
*/
|
||||
List<User> list32 = new ArrayList<User>();
|
||||
for(int i=1;i<=10;i++){
|
||||
list32.add(new User(i,"张三"+i));
|
||||
}
|
||||
|
||||
System.out.println("转换之前的数据:" + list32);// 转换之前的数据:[1, 2, 3]
|
||||
List<Map> list42 = list32.stream().map(User::toMap).collect(Collectors.toList());
|
||||
System.out.println("转换之后的数据:" + list42); // [1, 2, 3]
|
||||
|
||||
|
||||
/*
|
||||
* 获取平方
|
||||
*/
|
||||
List<Integer> list5 = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
|
||||
List<Integer> list6 = list5.stream().map(n -> n * n).collect(Collectors.toList());
|
||||
System.out.println("平方的数据:" + list6);// 转换之前的数据:[1, 4, 9, 16, 25]
|
||||
|
||||
/*
|
||||
* flatMap 一对多 得到多个数组里面的数字
|
||||
*/
|
||||
Stream<List<Integer>> inputStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
|
||||
Stream<Integer> outputStream = inputStream.flatMap((childList) -> childList.stream());
|
||||
System.out.println("打印 stream中的数字:");
|
||||
outputStream.forEach(System.out::println);
|
||||
|
||||
/*
|
||||
* 得到一段句子中的单词
|
||||
*/
|
||||
String worlds = "Never let success get to your head and never let failure get to your heart.";
|
||||
List<String> list7 = new ArrayList<>();
|
||||
list7.add(worlds);
|
||||
List<String> list8 = list7.stream().flatMap(str -> Stream.of(str.split(" ")))
|
||||
.filter(world -> world.length() > 0).collect(Collectors.toList());
|
||||
System.out.println("单词:");
|
||||
list8.forEach(System.out::println);
|
||||
|
||||
/*
|
||||
* peek 对每个元素执行操作并返回一个新的 Stream
|
||||
*/
|
||||
System.out.println("peek使用:");
|
||||
Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("转换之前: " + e))
|
||||
.map(String::toUpperCase).peek(e -> System.out.println("转换之后: " + e)).collect(Collectors.toList());
|
||||
|
||||
/*
|
||||
* limit 和 skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素(它是由一个叫
|
||||
* subStream 的方法改名而来)。
|
||||
*/
|
||||
List<User> list9 = new ArrayList<User>();
|
||||
for (int i = 1; i < 10; i++) {
|
||||
User user = new User(i, "pancm" + i);
|
||||
list9.add(user);
|
||||
}
|
||||
System.out.println("截取之前的数据:");
|
||||
// 取前5条数据,但是扔掉了前面的3条,可以理解为拿到的数据为 3<=i<5 (i 是数值下标)
|
||||
List<String> list10 = list9.stream().map(User::getName).limit(5).skip(3).collect(Collectors.toList());
|
||||
System.out.println("截取之后的数据:" + list10);
|
||||
|
||||
/*
|
||||
* sort 进行排序 先获取在排序效率更高
|
||||
*/
|
||||
System.out.println("排序之前的数据:");
|
||||
List<User> list11 = list9.stream().sorted((u1, u2) -> u1.getName().compareTo(u2.getName())).limit(3)
|
||||
.collect(Collectors.toList());
|
||||
System.out.println("排序之后的数据:" + list11);
|
||||
List<User> list12 = list9.stream().limit(3).sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
|
||||
.collect(Collectors.toList());
|
||||
System.out.println("优化排序之后的数据:" + list12);
|
||||
|
||||
/*
|
||||
* min/max/distinct
|
||||
* 最大,最小和去重
|
||||
*/
|
||||
BufferedReader br;
|
||||
int longest = 0;
|
||||
List<String> words = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("test.properties"));
|
||||
longest = br.lines().mapToInt(String::length).max().getAsInt();
|
||||
br.close();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("test.properties 最长的字符串的长度是:" + longest);
|
||||
|
||||
String lines = "good good study day day up";
|
||||
List<String> list13 = new ArrayList<String>();
|
||||
list13.add(lines);
|
||||
words = list13.stream().flatMap(line -> Stream.of(line.split(" "))).filter(word -> word.length() > 0)
|
||||
.map(String::toLowerCase).distinct().sorted().collect(Collectors.toList());
|
||||
System.out.println("去重复之后:" + words);
|
||||
|
||||
/*
|
||||
* Match 匹配
|
||||
*
|
||||
* allMatch:Stream 中全部元素符合传入的 predicate,返回 true anyMatch:Stream
|
||||
* 中只要有一个元素符合传入的 predicate,返回 true noneMatch:Stream 中没有一个元素符合传入的
|
||||
* predicate,返回 true
|
||||
*/
|
||||
|
||||
boolean all = lists.stream().allMatch(u -> u.getId() > 3);
|
||||
System.out.println("是否都大于3:" + all);
|
||||
boolean any = lists.stream().anyMatch(u -> u.getId() > 3);
|
||||
System.out.println("是否有一个大于3:" + any);
|
||||
boolean none = lists.stream().noneMatch(u -> u.getId() > 3);
|
||||
System.out.println("是否没有一个大于3的:" + none);
|
||||
|
||||
/*
|
||||
* 生成随机数 通过实现 Supplier 接口,你可以自己来控制流的生成。这种情形通常用于随机数、常量的
|
||||
* Stream,或者需要前后元素间维持着某种状态信息的 Stream。 把 Supplier 实例传递给 Stream.generate()
|
||||
* 生成的 Stream,默认是串行(相对 parallel 而言)但无序的(相对 ordered 而言)。
|
||||
* 由于它是无限的,在管道中,必须利用 limit 之类的操作限制 Stream 大小。
|
||||
*/
|
||||
Random seed = new Random();
|
||||
Supplier<Integer> random = seed::nextInt;
|
||||
System.out.println("生成5个随机数:");
|
||||
Stream.generate(random).limit(5).forEach(System.out::println);
|
||||
System.out.println("生成5正整数的随机数:");
|
||||
IntStream.generate(() -> (int) (System.nanoTime() % 100)).limit(5).forEach(System.out::println);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 一些关联使用
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static void test3() {
|
||||
|
||||
/*
|
||||
* Optional
|
||||
*/
|
||||
String strA = " abcd ", strB = null;
|
||||
System.out.println("数据校验开始...");
|
||||
print(strA);
|
||||
print("");
|
||||
print(strB);
|
||||
getLength(strA);
|
||||
getLength("");
|
||||
getLength(strB);
|
||||
System.out.println("数据校验结束...");
|
||||
|
||||
/*
|
||||
* reduce 主要作用是把 Stream 元素组合起来。
|
||||
*/
|
||||
// 字符串连接,concat = "ABCD"
|
||||
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
|
||||
System.out.println("字符串拼接:" + concat);
|
||||
// 求最小值,minValue = -3.0
|
||||
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
|
||||
System.out.println("最小值:" + minValue);
|
||||
// 求和,sumValue = 10, 有起始值
|
||||
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
|
||||
System.out.println("求和:" + sumValue);
|
||||
// 求和,sumValue = 10, 无起始值
|
||||
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
|
||||
System.out.println("求和:" + sumValue);
|
||||
// 过滤,字符串连接,concat = "ace"
|
||||
concat = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0).reduce("", String::concat);
|
||||
System.out.println("过滤和字符串连接:" + concat);
|
||||
|
||||
/*
|
||||
* iterate iterate 跟 reduce 操作很像,接受一个种子值,和一个 UnaryOperator(例如 f)。
|
||||
* 然后种子值成为 Stream 的第一个元素,f(seed) 为第二个,f(f(seed)) 第三个,以此类推。 在 iterate
|
||||
* 时候管道必须有 limit 这样的操作来限制 Stream 大小。
|
||||
*/
|
||||
// 生成一个等差队列
|
||||
Stream.iterate(0, n -> n + 3).limit(10).forEach(x -> System.out.print(x + " "));
|
||||
|
||||
/*
|
||||
* 分组排序 groupingBy/partitioningBy
|
||||
*/
|
||||
// 通过id进行排序
|
||||
System.out.println("通过id进行分组排序:");
|
||||
Map<Integer, List<User>> personGroups = Stream.generate(new UserSupplier2()).limit(5)
|
||||
.collect(Collectors.groupingBy(User::getId));
|
||||
Iterator it = personGroups.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<Integer, List<User>> persons = (Map.Entry) it.next();
|
||||
System.out.println("id " + persons.getKey() + " = " + persons.getValue());
|
||||
}
|
||||
|
||||
//通过年龄排序
|
||||
System.out.println("进行分区排序:");
|
||||
Map<Boolean, List<User>> children = Stream.generate(new UserSupplier2()).limit(5)
|
||||
.collect(Collectors.partitioningBy(p -> p.getId() < 18));
|
||||
|
||||
System.out.println("小孩: " + children.get(true));
|
||||
System.out.println("成年人: " + children.get(false));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义流
|
||||
*/
|
||||
private static void test4() {
|
||||
|
||||
/*
|
||||
* 自定义一个流 然后进行输出
|
||||
*/
|
||||
Stream.generate(new UserSupplier()).limit(2).forEach(u -> System.out.println(u.getId() + ", " + u.getName()));
|
||||
|
||||
}
|
||||
|
||||
public static void print(String text) {
|
||||
// jdk1.8之前的写法
|
||||
// if (text != null) {
|
||||
// System.out.println(text);
|
||||
// }
|
||||
// jdk1.8的写法
|
||||
Optional.ofNullable(text).ifPresent(System.out::println);
|
||||
}
|
||||
|
||||
public static void getLength(String text) {
|
||||
// jdk1.8之前的写法
|
||||
// return if (text != null) ? text.length() : -1;
|
||||
// jdk1.8的写法
|
||||
int i = Optional.ofNullable(text).map(String::length).orElse(-1);
|
||||
System.out.println("数据:" + i);
|
||||
};
|
||||
}
|
||||
|
||||
class UserSupplier implements Supplier<User> {
|
||||
private int index = 10;
|
||||
private Random random = new Random();
|
||||
|
||||
@Override
|
||||
public User get() {
|
||||
return new User(index++, "pancm" + random.nextInt(10));
|
||||
}
|
||||
}
|
||||
|
||||
class UserSupplier2 implements Supplier<User> {
|
||||
private int index = 10;
|
||||
private Random random = new Random();
|
||||
|
||||
@Override
|
||||
public User get() {
|
||||
return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
|
||||
}
|
||||
}
|
||||
package com.pancm.jdk8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.IntSummaryStatistics;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Title: StreamTest
|
||||
* @Description: Stream测试用例 流的操作类型分为两种:
|
||||
*
|
||||
* Intermediate:一个流可以后面跟随零个或多个 intermediate
|
||||
* 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。
|
||||
* 这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。 Terminal:一个流只能有一个
|
||||
* terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。 所以这必定是流的最后一个操作。 Terminal
|
||||
* 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
|
||||
* @Version:1.0.0
|
||||
* @author pancm
|
||||
* @date 2018年9月3日
|
||||
*/
|
||||
public class StreamTest {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
|
||||
/*
|
||||
* Stream 的特性可以归纳为:
|
||||
不是数据结构
|
||||
它没有内部存储,它只是用操作管道从 source(数据结构、数组、generator function、IO channel)抓取数据。
|
||||
它也绝不修改自己所封装的底层数据结构的数据。例如 Stream 的 filter 操作会产生一个不包含被过滤元素的新 Stream,而不是从 source 删除那些元素。
|
||||
所有 Stream 的操作必须以 lambda 表达式为参数
|
||||
不支持索引访问
|
||||
你可以请求第一个元素,但无法请求第二个,第三个,或最后一个。不过请参阅下一项。
|
||||
很容易生成数组或者 List
|
||||
惰性化
|
||||
很多 Stream 操作是向后延迟的,一直到它弄清楚了最后需要多少数据才会开始。
|
||||
Intermediate 操作永远是惰性化的。
|
||||
并行能力
|
||||
当一个 Stream 是并行化的,就不需要再写多线程代码,所有对它的操作会自动并行进行的。
|
||||
可以是无限的
|
||||
集合有固定大小,Stream 则不必。limit(n) 和 findFirst() 这类的 short-circuiting 操作可以对无限的 Stream 进行运算并很快完成。
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单实用
|
||||
*/
|
||||
private static void test1() {
|
||||
/*
|
||||
* 普通的方式过滤
|
||||
*/
|
||||
List<String> list = Arrays.asList("张三", "李四", "王五", "xuwujing");
|
||||
System.out.println("过滤之前:" + list);
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String str : list) {
|
||||
if (!"李四".equals(str)) {
|
||||
result.add(str);
|
||||
}
|
||||
}
|
||||
System.out.println("过滤之后:" + result);
|
||||
|
||||
/*
|
||||
* stream 过滤
|
||||
*/
|
||||
List<String> result2 = list.stream().filter(str -> !"李四".equals(str)).collect(Collectors.toList());
|
||||
System.out.println("stream 过滤之后:" + result2);
|
||||
// 另一种方式输出
|
||||
result2.forEach(System.out::println);
|
||||
|
||||
// 使用stream.filter ()过滤一列表,并.findAny().orElse
|
||||
// 遍历该list,查询数据,如果查不到,就返回 找不到!
|
||||
String result3 = list.stream().filter(str -> "李四".equals(str)).findAny().orElse("找不到!");
|
||||
String result4 = list.stream().filter(str -> "李二".equals(str)).findAny().orElse("找不到!");
|
||||
|
||||
System.out.println("stream 过滤之后 2:" + result3);
|
||||
System.out.println("stream 过滤之后 3:" + result4);
|
||||
//stream 过滤之后 2:李四
|
||||
//stream 过滤之后 3:找不到!
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本使用
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
|
||||
private static void test2() {
|
||||
|
||||
/*
|
||||
* 构造流的几种方式
|
||||
*/
|
||||
Stream stream = Stream.of("a", "b", "c");
|
||||
String[] strArray = new String[] { "a", "b", "c" };
|
||||
stream = Stream.of(strArray);
|
||||
stream = Arrays.stream(strArray);
|
||||
List<String> list = Arrays.asList(strArray);
|
||||
stream = list.stream();
|
||||
|
||||
/*
|
||||
* 流之间的相互转化 一个 Stream 只可以使用一次,这段代码为了简洁而重复使用了数次,因此会抛出异常
|
||||
*/
|
||||
try {
|
||||
Stream<String> stream2 = Stream.of("a", "b", "c");
|
||||
// 转换成 Array
|
||||
String[] strArray1 = stream2.toArray(String[]::new);
|
||||
|
||||
// 转换成 Collection
|
||||
List<String> list1 = stream2.collect(Collectors.toList());
|
||||
List<String> list2 = stream2.collect(Collectors.toCollection(ArrayList::new));
|
||||
Set set1 = stream2.collect(Collectors.toSet());
|
||||
Stack stack1 = stream2.collect(Collectors.toCollection(Stack::new));
|
||||
|
||||
// 转换成 String
|
||||
String str = stream.collect(Collectors.joining()).toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/*
|
||||
* 汇总操作
|
||||
*/
|
||||
List<User> lists = new ArrayList<User>();
|
||||
lists.add(new User(6, "张三"));
|
||||
lists.add(new User(2, "李四"));
|
||||
lists.add(new User(3, "王五"));
|
||||
lists.add(new User(1, "张三"));
|
||||
// 计算这个list中出现 "张三" id的值
|
||||
int sum = lists.stream().filter(u -> "张三".equals(u.getName())).mapToInt(u -> u.getId()).sum();
|
||||
|
||||
System.out.println("计算结果:" + sum);
|
||||
// 7
|
||||
|
||||
/*
|
||||
* 数值类型的流 包括IntStream, LongStream和DoubleStream
|
||||
*/
|
||||
System.out.println("遍历输出该数组的数据:");
|
||||
IntStream.of(new int[] { 1, 2, 3, 4 }).forEach(System.out::println);
|
||||
System.out.println("查询范围在 2-3(2<=i<3)之间的数据:");
|
||||
IntStream.range(2, 3).forEach(System.out::println);
|
||||
System.out.println("查询范围在2-3(2<=i<=3)之间的数据:");
|
||||
IntStream.rangeClosed(2, 3).forEach(System.out::println);
|
||||
|
||||
/* stream中的 map使用 */
|
||||
|
||||
/*
|
||||
* 转换大写
|
||||
*/
|
||||
List<String> list3 = Arrays.asList("zhangSan", "liSi", "wangWu");
|
||||
System.out.println("转换之前的数据:" + list3);
|
||||
List<String> list4 = list3.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
System.out.println("转换之后的数据:" + list4);
|
||||
// 转换之后的数据:[ZHANGSAN, LISI,WANGWU]
|
||||
|
||||
/*
|
||||
* 转换数据类型
|
||||
*/
|
||||
List<String> list31 = Arrays.asList("1", "2", "3");
|
||||
System.out.println("转换之前的数据:" + list31);
|
||||
List<Integer> list41 = list31.stream().map(Integer::valueOf).collect(Collectors.toList());
|
||||
System.out.println("转换之后的数据:" + list41);
|
||||
// [1, 2, 3]
|
||||
|
||||
|
||||
/*
|
||||
* 转换数据类型
|
||||
* 对象转map
|
||||
*/
|
||||
List<User> list32 = new ArrayList<User>();
|
||||
for(int i=1;i<=10;i++){
|
||||
list32.add(new User(i,"张三"+i));
|
||||
}
|
||||
|
||||
System.out.println("转换之前的数据:" + list32);// 转换之前的数据:[1, 2, 3]
|
||||
List<Map> list42 = list32.stream().map(User::toMap).collect(Collectors.toList());
|
||||
System.out.println("转换之后的数据:" + list42); // [1, 2, 3]
|
||||
|
||||
|
||||
/*
|
||||
* 获取平方
|
||||
*/
|
||||
List<Integer> list5 = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
|
||||
List<Integer> list6 = list5.stream().map(n -> n * n).collect(Collectors.toList());
|
||||
System.out.println("平方的数据:" + list6);
|
||||
// [1, 4, 9, 16, 25]
|
||||
|
||||
/*
|
||||
* flatMap 一对多 得到多个数组里面的数字
|
||||
*/
|
||||
Stream<List<Integer>> inputStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
|
||||
Stream<Integer> outputStream = inputStream.flatMap((childList) -> childList.stream());
|
||||
System.out.println("打印 stream中的数字:");
|
||||
outputStream.forEach(System.out::println);
|
||||
|
||||
/*
|
||||
* 得到一段句子中的单词
|
||||
*/
|
||||
String worlds = "The way of the future";
|
||||
List<String> list7 = new ArrayList<>();
|
||||
list7.add(worlds);
|
||||
List<String> list8 = list7.stream().flatMap(str -> Stream.of(str.split(" ")))
|
||||
.filter(world -> world.length() > 0).collect(Collectors.toList());
|
||||
System.out.println("单词:");
|
||||
list8.forEach(System.out::println);
|
||||
// 单词:
|
||||
// The
|
||||
// way
|
||||
// of
|
||||
// the
|
||||
// future
|
||||
|
||||
/*
|
||||
* peek 对每个元素执行操作并返回一个新的 Stream
|
||||
*/
|
||||
System.out.println("peek使用:");
|
||||
Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("转换之前: " + e))
|
||||
.map(String::toUpperCase).peek(e -> System.out.println("转换之后: " + e)).collect(Collectors.toList());
|
||||
|
||||
// 转换之前: three
|
||||
// 转换之后: THREE
|
||||
// 转换之前: four
|
||||
// 转换之后: FOUR
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* limit 和 skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素(它是由一个叫
|
||||
* subStream 的方法改名而来)。
|
||||
*/
|
||||
|
||||
//limit 简单使用
|
||||
Random rd = new Random();
|
||||
System.out.println("取到的前三条数据:");
|
||||
rd.ints().limit(3).forEach(System.out::println);
|
||||
// 取到的前三条数据:
|
||||
// 1167267754
|
||||
// -1164558977
|
||||
// 1977868798
|
||||
|
||||
List<User> list9 = new ArrayList<User>();
|
||||
for (int i = 1; i < 4; i++) {
|
||||
User user = new User(i, "pancm" + i);
|
||||
list9.add(user);
|
||||
}
|
||||
System.out.println("截取之前的数据:");
|
||||
// 取前3条数据,但是扔掉了前面的2条,可以理解为拿到的数据为 2<=i<3 (i 是数值下标)
|
||||
List<String> list10 = list9.stream().map(User::getName).limit(3).skip(2).collect(Collectors.toList());
|
||||
System.out.println("截取之后的数据:" + list10);
|
||||
// 截取之前的数据:
|
||||
// 姓名:pancm1
|
||||
// 姓名:pancm2
|
||||
// 姓名:pancm3
|
||||
// 截取之后的数据:[pancm3]
|
||||
|
||||
|
||||
/*
|
||||
* sort 进行排序 先获取在排序效率更高
|
||||
*/
|
||||
|
||||
Random rd2 = new Random();
|
||||
System.out.println("取到的前三条数据然后进行排序:");
|
||||
rd2.ints().limit(3).sorted().forEach(System.out::println);
|
||||
// 取到的前三条数据然后进行排序:
|
||||
// -2043456377
|
||||
// -1778595703
|
||||
// 1013369565
|
||||
|
||||
//普通的排序取值
|
||||
List<User> list11 = list9.stream().sorted((u1, u2) -> u1.getName().compareTo(u2.getName())).limit(3)
|
||||
.collect(Collectors.toList());
|
||||
System.out.println("排序之后的数据:" + list11);
|
||||
//优化排序取值
|
||||
List<User> list12 = list9.stream().limit(3).sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
|
||||
.collect(Collectors.toList());
|
||||
System.out.println("优化排序之后的数据:" + list12);
|
||||
//排序之后的数据:[{"id":1,"name":"pancm1"}, {"id":2,"name":"pancm2"}, {"id":3,"name":"pancm3"}]
|
||||
//优化排序之后的数据:[{"id":1,"name":"pancm1"}, {"id":2,"name":"pancm2"}, {"id":3,"name":"pancm3"}]
|
||||
|
||||
/*
|
||||
* min/max/distinct
|
||||
* 最大,最小和去重
|
||||
*/
|
||||
|
||||
List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xuwujing");
|
||||
int maxLines = list13.stream().mapToInt(String::length).max().getAsInt();
|
||||
int minLines = list13.stream().mapToInt(String::length).min().getAsInt();
|
||||
System.out.println("最长字符的长度:" + maxLines+",最短字符的长度:"+minLines);
|
||||
//最长字符的长度:8,最短字符的长度:4
|
||||
|
||||
String lines = "good good study day day up";
|
||||
List<String> list14 = new ArrayList<String>();
|
||||
list14.add(lines);
|
||||
List<String> words = list14.stream().flatMap(line -> Stream.of(line.split(" "))).filter(word -> word.length() > 0)
|
||||
.map(String::toLowerCase).distinct().sorted().collect(Collectors.toList());
|
||||
System.out.println("去重复之后:" + words);
|
||||
//去重复之后:[day, good, study, up]
|
||||
|
||||
/*
|
||||
* Match 匹配
|
||||
*
|
||||
* allMatch:Stream 中全部元素符合则返回 true ;
|
||||
* anyMatch:Stream 中只要有一个元素符合则返回 true;
|
||||
* noneMatch:Stream 中没有一个元素符合则返回 true。
|
||||
*/
|
||||
|
||||
boolean all = lists.stream().allMatch(u -> u.getId() > 3);
|
||||
System.out.println("是否都大于3:" + all);
|
||||
boolean any = lists.stream().anyMatch(u -> u.getId() > 3);
|
||||
System.out.println("是否有一个大于3:" + any);
|
||||
boolean none = lists.stream().noneMatch(u -> u.getId() > 3);
|
||||
System.out.println("是否没有一个大于3的:" + none);
|
||||
// 是否都大于3:false
|
||||
// 是否有一个大于3:true
|
||||
// 是否没有一个大于3的:false
|
||||
|
||||
/*
|
||||
* 生成随机数 通过实现 Supplier 接口,你可以自己来控制流的生成。这种情形通常用于随机数、常量的
|
||||
* Stream,或者需要前后元素间维持着某种状态信息的 Stream。 把 Supplier 实例传递给 Stream.generate()
|
||||
* 生成的 Stream,默认是串行(相对 parallel 而言)但无序的(相对 ordered 而言)。
|
||||
* 由于它是无限的,在管道中,必须利用 limit 之类的操作限制 Stream 大小。
|
||||
*/
|
||||
Random seed = new Random();
|
||||
seed.ints().limit(3).forEach(System.out::println);
|
||||
Supplier<Integer> random = seed::nextInt;
|
||||
System.out.println("生成5个随机数:");
|
||||
Stream.generate(random).limit(3).forEach(System.out::println);
|
||||
System.out.println("生成5正整数的随机数:");
|
||||
IntStream.generate(() -> (int) (System.nanoTime() % 100)).limit(3).forEach(System.out::println);
|
||||
System.out.println("生成5个随机数:");
|
||||
|
||||
|
||||
/*
|
||||
并行(parallel)程序
|
||||
parallelStream 是流并行处理程序的代替方法。
|
||||
*/
|
||||
List<String> strings = Arrays.asList("a", "", "c", "", "e","", " ");
|
||||
// 获取空字符串的数量
|
||||
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
|
||||
System.out.println("空字符串的个数:"+count);
|
||||
|
||||
|
||||
/*
|
||||
* 合并字符串
|
||||
*/
|
||||
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
|
||||
System.out.println("筛选列表: " + filtered);
|
||||
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
|
||||
System.out.println("合并字符串: " + mergedString);
|
||||
// 筛选列表: [a, c, e, ]
|
||||
// 合并字符串: a, c, e,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 一些关联使用
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static void test3() {
|
||||
|
||||
/*
|
||||
* Optional
|
||||
*/
|
||||
String strA = " abcd ", strB = null;
|
||||
System.out.println("数据校验开始...");
|
||||
print(strA);
|
||||
print("");
|
||||
print(strB);
|
||||
getLength(strA);
|
||||
getLength("");
|
||||
getLength(strB);
|
||||
System.out.println("数据校验结束...");
|
||||
|
||||
/*
|
||||
* reduce 主要作用是把 Stream 元素组合起来。
|
||||
*/
|
||||
// 字符串连接,concat = "ABCD"
|
||||
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
|
||||
System.out.println("字符串拼接:" + concat);
|
||||
//字符串拼接:ABCD
|
||||
// 求最小值
|
||||
double minValue = Stream.of(-4.0, 1.0, 3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
|
||||
System.out.println("最小值:" + minValue);
|
||||
//最小值:-4.0
|
||||
|
||||
|
||||
// 求和, 无起始值
|
||||
int sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
|
||||
System.out.println("有无起始值求和:" + sumValue);
|
||||
// 求和, 有起始值
|
||||
sumValue = Stream.of(1, 2, 3, 4).reduce(1, Integer::sum);
|
||||
System.out.println("有起始值求和:" + sumValue);
|
||||
// 有无起始值求和:10
|
||||
// 有起始值求和:11
|
||||
|
||||
|
||||
// 过滤,字符串连接,concat = "ace"
|
||||
concat = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0).reduce("", String::concat);
|
||||
System.out.println("过滤和字符串连接:" + concat);
|
||||
//过滤和字符串连接:ace
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* iterate iterate 跟 reduce 操作很像,接受一个种子值,和一个 UnaryOperator(例如 f)。
|
||||
* 然后种子值成为 Stream 的第一个元素,f(seed) 为第二个,f(f(seed)) 第三个,以此类推。 在 iterate
|
||||
* 时候管道必须有 limit 这样的操作来限制 Stream 大小。
|
||||
*/
|
||||
System.out.println("从2开始生成一个等差队列:");
|
||||
Stream.iterate(2, n -> n + 2).limit(5).forEach(x -> System.out.print(x + " "));
|
||||
// 从2开始生成一个等差队列:
|
||||
// 2 4 6 8 10
|
||||
|
||||
|
||||
System.out.println("\n");
|
||||
/*
|
||||
* 分组排序 groupingBy/partitioningBy
|
||||
*/
|
||||
// 通过id进行排序
|
||||
System.out.println("通过id进行分组排序:");
|
||||
Map<Integer, List<User>> personGroups = Stream.generate(new UserSupplier2()).limit(5)
|
||||
.collect(Collectors.groupingBy(User::getId));
|
||||
Iterator it = personGroups.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<Integer, List<User>> persons = (Map.Entry) it.next();
|
||||
System.out.println("id " + persons.getKey() + " = " + persons.getValue());
|
||||
}
|
||||
|
||||
// 通过id进行分组排序:
|
||||
// id 10 = [{"id":10,"name":"pancm1"}]
|
||||
// id 11 = [{"id":11,"name":"pancm3"}, {"id":11,"name":"pancm6"}, {"id":11,"name":"pancm4"}, {"id":11,"name":"pancm7"}]
|
||||
|
||||
|
||||
|
||||
//通过年龄排序
|
||||
System.out.println("通过年龄进行分区排序:");
|
||||
Map<Boolean, List<User>> children = Stream.generate(new UserSupplier3()).limit(5)
|
||||
.collect(Collectors.partitioningBy(p -> p.getId() < 18));
|
||||
|
||||
System.out.println("小孩: " + children.get(true));
|
||||
System.out.println("成年人: " + children.get(false));
|
||||
|
||||
// 通过年龄进行分区排序:
|
||||
// 小孩: [{"id":16,"name":"pancm7"}, {"id":17,"name":"pancm2"}]
|
||||
// 成年人: [{"id":18,"name":"pancm4"}, {"id":19,"name":"pancm9"}, {"id":20,"name":"pancm6"}]
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IntSummaryStatistics 用于收集统计信息(如count、min、max、sum和average)的状态对象。
|
||||
*/
|
||||
List<Integer> numbers = Arrays.asList(1, 5, 7, 3, 9);
|
||||
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
|
||||
|
||||
System.out.println("列表中最大的数 : " + stats.getMax());
|
||||
System.out.println("列表中最小的数 : " + stats.getMin());
|
||||
System.out.println("所有数之和 : " + stats.getSum());
|
||||
System.out.println("平均数 : " + stats.getAverage());
|
||||
|
||||
// 列表中最大的数 : 9
|
||||
// 列表中最小的数 : 1
|
||||
// 所有数之和 : 25
|
||||
// 平均数 : 5.0
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义流
|
||||
*/
|
||||
private static void test4() {
|
||||
|
||||
/*
|
||||
* 自定义一个流 然后进行输出
|
||||
*/
|
||||
System.out.println("自定义一个流进行计算输出:");
|
||||
Stream.generate(new UserSupplier()).limit(2).forEach(u -> System.out.println(u.getId() + ", " + u.getName()));
|
||||
|
||||
//第一次:
|
||||
//自定义一个流进行计算输出:
|
||||
//10, pancm7
|
||||
//11, pancm6
|
||||
|
||||
//第二次:
|
||||
//自定义一个流进行计算输出:
|
||||
//10, pancm4
|
||||
//11, pancm2
|
||||
|
||||
//第三次:
|
||||
//自定义一个流进行计算输出:
|
||||
//10, pancm4
|
||||
//11, pancm8
|
||||
}
|
||||
|
||||
public static void print(String text) {
|
||||
// jdk1.8之前的写法
|
||||
// if (text != null) {
|
||||
// System.out.println(text);
|
||||
// }
|
||||
// jdk1.8的写法
|
||||
Optional.ofNullable(text).ifPresent(System.out::println);
|
||||
}
|
||||
|
||||
public static void getLength(String text) {
|
||||
// jdk1.8之前的写法
|
||||
// return if (text != null) ? text.length() : -1;
|
||||
// jdk1.8的写法
|
||||
int i = Optional.ofNullable(text).map(String::length).orElse(-1);
|
||||
System.out.println("数据:" + i);
|
||||
};
|
||||
}
|
||||
|
||||
class UserSupplier implements Supplier<User> {
|
||||
private int index = 10;
|
||||
private Random random = new Random();
|
||||
|
||||
@Override
|
||||
public User get() {
|
||||
return new User(index++, "pancm" + random.nextInt(10));
|
||||
}
|
||||
}
|
||||
|
||||
class UserSupplier2 implements Supplier<User> {
|
||||
private int index = 10;
|
||||
private Random random = new Random();
|
||||
|
||||
@Override
|
||||
public User get() {
|
||||
return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
|
||||
}
|
||||
}
|
||||
|
||||
class UserSupplier3 implements Supplier<User> {
|
||||
private int index = 16;
|
||||
private Random random = new Random();
|
||||
|
||||
@Override
|
||||
public User get() {
|
||||
return new User(index++, "pancm" + random.nextInt(10));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user