1 Lamde表达式 -->后为要执行的代码
格式:
左侧:Lambda 表达式的参数列表 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
语法格式一:无参数,无返回值 System.out.println("Hello Lambda!");
语法格式二:有一个参数,并且无返回值 (x) -> System.out.println(x)
语法格式三:若只有一个参数,小括号可以省略不写 x -> System.out.println(x)
语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
Comparator<Integer> com = (x, y) -> {
System.out.println("函数式接口");
return Integer.compare(x, y);
};
语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断” (Integer x, Integer y) -> Integer.compare(x, y);
1、加粗部分(星号内)为要执行的代码 也就是retrun的代码
-
@Test public void tedt1( ) { String trimStr = strHandler("\t\t\t 我是好人 ", (str) -> **str.trim()**); System.out.println(trimStr); String upper = strHandler("abcdef", (str) -> **str.toUpperCase(**)); System.out.println(upper); String newStr = strHandler("123 我是好人", (str) -> **str.substring(2, 5)**); System.out.println(newStr); }
2、测试:
1、获取员工工资大于5000的
2、:获取公司中年龄小于 35 的员工信息
List<Employee> emps = Arrays.asList(
new Employee(101, "张三", 18, 9999.99),
new Employee(102, "李四", 59, 6666.66),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "赵六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55));
过滤方法:
//优化方式一:策略设计模式
public List<Employee> filterEmployee(List<Employee> emps, MyPredicate<Employee> mp){
List<Employee> list = new ArrayList<>();
for (Employee employee : emps) {
if(mp.test(employee)){
list.add(employee);
}
}
return list;
}
### lamde表达式:
@Test
public void test6(){
List<Employee> list = filterEmployee(emps, (e) -> e.getAge() <= 35);
list.forEach(System.out::println);
System.out.println("------------------------------------------");
List<Employee> list2 = filterEmployee(emps, (e) -> e.getSalary() >= 5000);
list2.forEach(System.out::println);
}
// ☆ ☆ ☆ ☆优化方式四:Stream API ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆
@Test
public void test7(){
emps.stream()
.filter((e) -> e.getAge() <= 35)
.forEach(System.out::println);
System.out.println("----------------------------------------------");
emps.stream()
.map(Employee::getName)
.limit(3)
.sorted()
.forEach(System.out::println);
}
java8-函数接口
Consumer < T > | 接受一个输入参数并且无返回的操作 。方法:void accept(T t) |
Supplier < T > | 无参数,返回类型为T的对象,方法:T get();。 |
Function<T, R> | 对类型为T的对象应用操作,并返回R类型的对象。方法:R apply(T t); |
Predicate< T > | 确定类型为T的对象是否满足某约束,并返回boolean 值。方法boolean test(T t); |
四大类型接口子接口 | 四大类型接口子接口 |
-Consumer- | – |
BiConsumer<T,U> | 对类型为T, U 参数应用操作。包含方法为void accept(T t, U u) |
DoubleConsumer | 接受double值参数的操作,并且不返回结果。 |
IntConsumer | 接受int类型的输入参数,无返回值 。 |
LongConsumer | 接受long类型的输入参数,无返回值。 |
ObjDoubleConsumer< T > | 接受T类型和double类型的输入参数,无返回值。 |
ObjIntConsumer< T > | 接受T类型和int类型的输入参数,无返回值。 |
ObjLongConsumer< T > | 接受T类型和ong类型的输入参数,无返回值。 |
-Predicate- | – |
BiPredicate<T,U> | 代表了一个两个参数的boolean值方法 |
DoublePredicate | 代表一个拥有double值参数的boolean值方法 |
IntPredicate | 接受一个int输入参数,返回一个布尔值的结果。 |
LongPredicate | R接受一个long输入参数,返回一个布尔值类型结果。 |
Predicate< T > | 接受一个输入参数,返回一个布尔值结果。 |
-Supplier- | – |
BooleanSupplier | 代表了boolean值结果的提供方 |
DoubleSupplier | 代表一个double值结构的提供方 |
IntSupplier | 无参数,返回一个int类型结果。 |
LongSupplier | 无参数,返回一个结果long类型的值。 |
-Function- | – |
BiFunction<T,U,R> | 对类型为 T, U 参数应用操作,返回 R 类型的结果。包含方法为R apply(T t, U u); |
DoubleFunction< R> | 代表接受一个double值参数的方法,并且返回结果 |
DoubleToLongFunction | 接受一个double类型输入,返回一个long类型结果 |
Function<T,R> | 接受一个输入参数,返回一个结果。 |
IntFunction< R > | 接受一个int类型输入参数,返回一个结果 。 |
IntToDoubleFunction | 接受一个int类型输入,返回一个double类型结果 。 |
IntToLongFunction | 接受一个int类型输入,返回一个long类型结果。 |
LongFunction< R > | 接受一个long类型输入参数,返回一个结果。 |
LongToDoubleFunction | 接受一个long类型输入,返回一个double类型结果。 |
ToDoubleBiFunction<T,U> | 接受两个输入参数,返回一个double类型结果 |
ToDoubleFunction< T > | 接受一个输入参数,返回一个double类型结果 |
ToIntBiFunction<T,U> | 接受两个输入参数,返回一个int类型结果。 |
ToLongBiFunction<T,U> | 接受两个输入参数,返回一个long类型结果。 |
ToLongFunction< T > | 接受一个输入参数,返回一个long类型结果。 |
BinaryOperator< T > | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为T apply(T t1, T t2); |
DoubleBinaryOperator | 作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
DoubleUnaryOperator | 接受一参数同为类型double,返回值类型也为double 。 |
IntBinaryOperator | 接受两个参数同为类型int,返回值类型也为int 。 |
IntUnaryOperator | 接受一个参数同为类型int,返回值类型也为int 。 |
LongBinaryOperator | 接受两个参数同为类型long,返回值类型也为long。 |
LongUnaryOperator | 接受一个参数同为类型long,返回值类型也为long。 |
UnaryOperator< T > | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为T apply(T t); |
方法引用 使用一对冒号 :: 。
@Test
public void test1(){
Consumer<String> con2 = ps::println;
**con2.accept("Hello Java8!");**
Consumer<String> con3 = System.out::println;
}
注意:当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引
用方法的第二个参数(或无参数)时:ClassName::methodName
构造器引用 格式: ClassName::new
数组引用 格式: type[] :: new
Stream 集合讲的是数据,流讲的是计算!
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
Collections
stream() : 返回一个顺序流
parallelStream() : 返回一个并行流
创建流的方式
1、由数组创建流:Arrays.stream()
2、由值创建流: Stream.of(),
☆☆ 3、由函数创建流:无限流
1、 静态方法 迭代 Stream.iterate()和
2、生成 Stream.generate(),☆☆
public void test11(){
//1. Collection 提供了两个方法 stream() 与 parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
//2. 通过 Arrays 中的 stream() 获取一个数组流
Integer[] nums = new Integer[10];
Stream<Integer> stream1 = Arrays.stream(nums);
//3. 通过 Stream 类中静态方法 of()
Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
//4. 创建无限流
//迭代
Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
stream3.forEach(System.out::println);
//生成
Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
stream4.forEach(System.out::println);
}
☆☆ Stream 的中间件操作
☆☆筛选与切片☆☆
方 法 | 描 述 |
filter(Predicate p) | 接收 Lambda , 从流中排除某些元素。 |
distinct() | 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 |
limit(long maxSize) | 截断流,使其元素不超过给定数量。 |
skip(long n) | 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 |
☆☆映射☆☆
map(Function f) | 接收一个函数作为参数,该函数会被应用到每素上,并将其映射成一个新的元素。 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每素上,产生一个新的DoubleStream |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每素上,产生一个新的IntStream。 |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每素上,产生一个新的LongStream。 |
flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换一个流,然后把所有流连接成一个流 |
sorted() | 产生一个新流,其中按自然顺序排序 |
sorted(Comparator comp) | 产生一个新流,其中按比较器顺序排序 |
map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素(嵌套的)。
★ ★ ★ ★ ★ flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流(**非嵌套的)**★ ★ ★ ★
@Test
public void test1(){
Stream<String> str = emps.stream()
.map((e) -> e.getName());
System.out.println("-------------------------------------------");
List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
Stream<String> stream = strList.stream()
.map(String::toUpperCase);
stream.forEach(System.out::println);
**Stream<Stream<Character>> stream2** = strList.stream()
.map(TestStreamAPI1::filterCharacter);
stream2.forEach((sm) -> {
sm.forEach(System.out::println);
});
System.out.println("---------------------------------------------");
**Stream<Character> stream3** = strList.stream()
.flatMap(TestStreamAPI1::filterCharacter);
stream3.forEach(System.out::println);
}
public static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
/*
sorted()——自然排序
sorted(Comparator com)——定制排序
*/
@Test
public void test2(){
emps.stream()
.map(Employee::getName)
.sorted()
.forEach(System.out::println);
System.out.println("------------------------------------");
emps.stream()
.sorted((x, y) -> {
if(x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(), y.getAge());
}
}).forEach(System.out::println);
}
Stream 的终止操作
1、查找与匹配
方法 | 描述 |
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
findFirst() | 返回第一个元素findAny() 返回当前流中的任意元素 |
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了) |
2\归约
方法 | 描述 |
reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 Optional< T > |
reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
@Test
public void test1(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println(sum);
System.out.println("----------------------------------------");
Optional<Double> op = emps.stream()
.map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(op.get());
}
3\收集
方法 | 描述 |
collect(Collector c) | 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法 |
具体方法如下
方法 | 返回类型 | 作用 |
toList | List< T > | 把流中元素收集到List |
List< Employee > emps= list.stream().collect(Collectors.toList()); | ||
toSet | Set< T > | 把流中元素收集到Set |
Set< Employee> emps= list.stream().collect(Collectors.toSet()); | ||
toCollection | Collection< T > | 把流中元素收集到创建的集合 |
Collection< Employee>emps=list.stream().collect(Collectors.toCollection(ArrayList::new)); | ||
counting | Long | 计算流中元素的个数 |
long count = list.stream().collect(Collectors.counting()); | ||
summingInt | Integer | 对流中元素的整数属性求和 |
inttotal=list.stream().collect(Collectors.summingInt(Employee::getSalary)); | ||
averagingInt | Double | 计算流中元素Integer属性的平均值 |
doubleavg= list.stream().collect(Collectors.averagingInt(Employee::getSalary)); | ||
summarizingInt | IntSummaryStatistics | 收集流中Integer属性的统计值。如:平均值 |
joining | String | 连接流中每个字符串 |
String str= list.stream().map(Employee::getName).collect(Collectors.joining()); | ||
maxBy | Optional< T > | 根据比较器选择最大值 |
Optional< Emp>max= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary))); | ||
minBy | Optional< T > | 根据比较器选择最小值 |
Optional< Emp> min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary))); | ||
reducing | 归约产生的类型 | 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值 |
inttotal=list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum)); | ||
collectingAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结果转换函数 |
inthow= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size)); | ||
groupingBy | Map<K, List< T >> | 根据某属性值对流分组,属性为K,结果为V |
使用 LocalDate、LocalTime、LocalDateTime
LocalDate、LocalTime、LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601日
历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信
息。也不包含与时区相关的信息。
now() 静态方法, | 根据当前时间创建对象 | LocalDate localDate = LocalDate.now();LocalTime localTime = LocalTime.now();LocalDateTime localDateTime = LocalDateTime.now(); |
of() 静态方法, | 根据指定日期/时间创建对象 | LocalDate localDate = LocalDate.of(2016, 10, 26);LocalTime localTime = LocalTime.of(02, 22, 56);LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55); |
plusDays, plusWeeks,plusMonths, plusYears | 向当前 LocalDate 对象添加几天、几周、几个月、几年 | |
minusDays, minusWeeks,minusMonths, minusYears | 从当前 LocalDate 对象减去几天、几周、几个月、几年 | |
plus, minus | 添加或减少一个 Duration 或 Period | |
withDayOfMonth,withDayOfYear,withMonth,withYear | 将月份天数、年份天数、月份、年份 修 改 为 指 定 的 值 并 返回 新 的LocalDate 对象 | |
getDayOfMonth | 获得月份天数(1-31) | |
getDayOfYear | 获得年份天数(1-366) | |
getDayOfWeek | 获得星期几(返回一个 DayOfWeek枚举值) | |
getMonth | 获得月份, 返回一个 Month 枚举值 | |
getMonthValue | 获得月份(1-12) | |
getYear | 获得年份 | |
until | 获得两个日期之间的 Period 对象,或者指定 ChronoUnits 的数字 | |
isBefore, isAfter | 比较两个 LocalDate | |
isLeapYear | 判断是否是闰年 |
Instant 时间戳
Duration 和 Period
Duration:用于计算两个“时间”间隔
Period:用于计算两个“日期”间隔
日期的操纵
1、TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作
2、TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。
解析与格式化
java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:
预定义的标准格式
语言环境相关的格式
自定义的格式
时区的处理
带时区的时间为分别为:ZonedDate、ZonedTime、ZonedDateTime
其中每个时区都对应着 ID,地区ID都为 “{区域}/{城市}”的格式
例如 :Asia/Shanghai 等
ZoneId:该类中包含了所有的时区信息
getAvailableZoneIds() : 可以获取所有时区时区信息
of(id) : 用指定的时区信息获取 ZoneId 对象
与传统日期处理的转换
类 | To 遗留类 | form遗留类 |
java.time.Instant , java.util.Date | Date.from(instant) | date.toInstant() |
java.time.Instant , java.sql.Timestamp | Timestamp.from(instant) | timestamp.toInstant() |
java.time.ZonedDateTime , java.util.GregorianCalendar | GregorianCalendar.from(zonedDateTime) | cal.toZonedDateTime() |
java.time.LocalDate , java.sql.Time | Date.valueOf(localDate) | date.toLocalDate() |
java.time.LocalTime , java.sql.Time | Date.valueOf(localDate) | date.toLocalTime() |
java.time.LocalDateTime , java.sql.Timestamp | Timestamp.valueOf(localDateTime) | timestamp.toLocalDateTime() |
java.time.ZoneId , java.util.TimeZone | Timezone.getTimeZone(id) | timeZone.toZoneId() |
java.time.format.DateTimeFormatter , java.text.DateFormat | formatter.toFormat() | 无 |
//6.ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
@Test
public void test7(){
LocalDateTime ldt = LocalDateTime.now(ZoneId.of(“Asia/Shanghai”));
System.out.println(ldt);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
System.out.println(zdt);
}
//5. DateTimeFormatter : 解析和格式化日期或时间
@Test
public void test5(){
// DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");
LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);
LocalDateTime newLdt = ldt.parse(strDate, dtf);
System.out.println(newLdt);
}
//4. TemporalAdjuster : 时间校正器
@Test
public void test4(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2);
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);
//自定义:下一个工作日
LocalDateTime ldt5 = ldt.with((l) -> {
LocalDateTime ldt4 = (LocalDateTime) l;
DayOfWeek dow = ldt4.getDayOfWeek();
if(dow.equals(DayOfWeek.FRIDAY)){
return ldt4.plusDays(3);
}else if(dow.equals(DayOfWeek.SATURDAY)){
return ldt4.plusDays(2);
}else{
return ldt4.plusDays(1);
}
});
System.out.println(ldt5);
}
//3.
//Duration : 用于计算两个“时间”间隔
//Period : 用于计算两个“日期”间隔
@Test
public void test3(){
Instant ins1 = Instant.now();
System.out.println("--------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Instant ins2 = Instant.now();
System.out.println("所耗费时间为:" + Duration.between(ins1, ins2));
System.out.println("----------------------------------");
LocalDate ld1 = LocalDate.now();
LocalDate ld2 = LocalDate.of(2011, 1, 1);
Period pe = Period.between(ld2, ld1);
System.out.println(pe.getYears());
System.out.println(pe.getMonths());
System.out.println(pe.getDays());
}
//2. Instant : 时间戳。 (使用 Unix 元年 1970年1月1日 00:00:00 所经历的毫秒值)
@Test
public void test2(){
Instant ins = Instant.now(); //默认使用 UTC 时区
System.out.println(ins);
OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);
System.out.println(ins.getNano());
Instant ins2 = Instant.ofEpochSecond(5);
System.out.println(ins2);
}
//1. LocalDate、LocalTime、LocalDateTime
@Test
public void test1(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
System.out.println(ld2);
LocalDateTime ldt3 = ld2.plusYears(20);
System.out.println(ldt3);
LocalDateTime ldt4 = ld2.minusMonths(2);
System.out.println(ldt4);
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
}
Optional 类
常用方法:
Optional.of(T t) : 创建一个 Optional 实例
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
isPresent() : 判断是否包含值
orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
@Test
public void test4(){
Optional op = Optional.of(new Employee(101, “张三”, 18, 9999.99));
Optional<String> op2 = op.map(Employee::getName);
System.out.println(op2.get());
Optional<String> op3 = op.flatMap((e) -> Optional.of(e.getName()));
System.out.println(op3.get());
}
@Test
public void test3(){
Optional<Employee> op = Optional.ofNullable(new Employee());
if(op.isPresent()){
System.out.println(op.get());
}
Employee emp = op.orElse(new Employee("张三"));
System.out.println(emp);
Employee emp2 = op.orElseGet(() -> new Employee());
System.out.println(emp2);
}
public String getGodnessName2(Optional<NewMan> man){
return man.orElse(new NewMan())
.getGodness()
.orElse(new Godness("苍老师"))
.getName();
}
重复注解与类型注解
流的可分解性
这就说到流的可分解性问题了,使用并行的时候,我们要注意流背后的数据结构是否易于分解。比如众所周知的 ArrayList 和 LinkedList,明显前者在分解方面占优。
我们来看看一些数据源的可分解性情况
数据源 可分解性
ArrayList 极佳
LinkedList 差
IntStream.range 极佳
Stream.iterate 差
HashSet 好
TreeSet 好
除了可分解性,和刚刚提到的装箱问题,还有一点值得注意的是一些操作本身在并行流上的性能就比顺序流要差,比如:limit,findFirst,因为这两个方法会考虑元素的顺序性,而并行本身就是违背顺序性的,也是因为如此 findAny 一般比 findFirst 的效率要高
LongStream 中的 range 和rangeClosed方法的区别
差别就是rangeClosed包含最后的结束节点,range不包含。
@Test
public void rangedTest() {
LongStream ls = LongStream.range(2L, 5L);
long[] lsA = ls.toArray();
for (long l : lsA) {
System.out.println(l);
}
}
运行结果 2 3 4
@Test
public void rangedClosedTest() {
LongStream ls = LongStream.rangeClosed(2L, 5L);
long[] lsA = ls.toArray();
for (long l : lsA) {
System.out.println(l);
}
}
运行结果 2 3 4 5
备注 研究下RecursiveTask 有返回值 action无返回值
重复注解 研究下
☆☆☆☆left.fork(); //拆分,并将该子任务压入线程队列 研究下☆☆☆☆☆
public class ForkJoinCalculate extends RecursiveTask{
/**
*
*/
private static final long serialVersionUID = 13475679780L;
private long start;
private long end;
private static final long THRESHOLD = 10000L; //临界值
public ForkJoinCalculate(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end - start;
if(length <= THRESHOLD){
long sum = 0;
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
}else{
long middle = (start + end) / 2;
ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
**left.fork(); //拆分,并将该子任务压入线程队列 研究下**
ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
**right.fork();**
return left.join() + right.join();
}
}
}
@Test
public void test1(){
long start = System.currentTimeMillis();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);
long sum = pool.invoke(task);
System.out.println(sum);
long end = System.currentTimeMillis();
System.out.println("耗费的时间为: " + (end - start)); //112-1953-1988-2654-2647-20663-113808
}
java8 并行流操作
@Test
public void test3(){
long start = System.currentTimeMillis();
Long sum = LongStream.rangeClosed(0L, 10000000000L)
.parallel()
.sum();
System.out.println(sum);
long end = System.currentTimeMillis();
System.out.println("耗费的时间为: " + (end - start)); //2061-2053-2086-18926
}