java8新特性
Table of Contents generated with DocToc (opens new window)
# java8:
返回类型
consumer< T> 消费型接口 void 对类型为T的对象进行应用操作,包含方法 void accept(T t)
supplier< T> 供给型接口 T 返回类型为T的对象,包含方法: T get()
function<T,R>函数型接口 R 对类型为T 的对象应用操作,并返回结果。结果类型为R类型的 的对象 R apply(T t)
perdicate< T> 断定型接口 boolean 确定类型为T的对象是否满足某约束条件,并返回boolean
包含方法 Boolean test(T t)
表达式:
(parameters)->expression
(parameters) ->(statments;)
()->{return "hello";}
()->{return "hello world";}
(integer i) -> {return "Alex"+i}
(String s)-> {return "hello Alex";}
Comparator<Apple> byColor = new Comparator<Apple>() {
public int compare(Apple o1, Apple o2) {
return o1.getColor().compareTo(o2.getColor());
}
};
List<Apple> list= Collections.emptyList();
list.sort(byColor);
// parameter list arrow lambda body
Comparator<Apple> byColor2 = (o1,o2)-> o1.getColor().compareTo(o2.getColor());
Function<String,Integer> flambe= s -> s.length();
2
3
4
5
6
7
8
9
10
函数式接口:
# Consumer接口
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* 可实现方法,接受一个参数且没有返回值
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* 默认方法,提供链式调用方式执行。执行流程:先执行本身的accept在执行传入参数after.accept方法。
* 该方法会抛出NullPointerException异常。
* 如果在执行调用链时出现异常,会将异常传递给调用链功能的调用者,且发生异常后的after将不会在调用。
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Predicate :
根据给定的规则,过滤集合中的字符串,规则由predicate的方法决定
private static List<Apple> filterByWeight(List<Apple> source , LongPredicate predicate){
List<Apple> result = new ArrayList<>();
for (Apple apple:source){
if(predicate.test(apple.getWeight())){
result.add(apple);
}
}
return result;
}
public void testFilterByWeight(){
List<Apple> list = Arrays.asList(new Apple("green", 150), new Apple("yellow", 120), new Apple("green", 120));
List<Apple> appleList = filterByWeight(list, w -> w>100);
System.out.println(appleList);
}
@Test
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
传入两个参数:
private static List<Apple> filterBiPredicate(List<Apple> source , BiPredicate<String,Long> predicate){
List<Apple> result = new ArrayList<>();
for (Apple apple:source){
if(predicate.test(apple.getColor(),apple.getWeight())){
result.add(apple);
}
}
return result;
}
@Test
public void testFilterBiPredicate(){
List<Apple> list = Arrays.asList(new Apple("green", 150), new Apple("yellow", 120), new Apple("green", 120));
List<Apple> appleList = filterBiPredicate(list,(s,w)->s.equals("green")&&w>100);
System.out.println(appleList);
}
@Test
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
方法体的引用与构造器 的引用 :
collection是一种静态的内存的数据结构,讲的是数据,而Steam是有关计算的与cpu
没有中间操作不会执行延迟操作
# 创建Stream
创建Stream 方式一:通过集合
// 通过集合方式进行创建
@Test
public void Test(){
List<Employee> employees = EmployeeData.getEmployees();
// default Stream<E> stream():返回一个顺序流
Stream<Employee> stream =employees.stream();
// default Stream<E> parallelStream():返回一个并行流
Stream<Employee> employeeStream = employees.parallelStream();
}
2
3
4
5
6
7
8
9
# 方式二:通过数组:
Java8中的Arrays的静态方法stream()可以获取数组流:
- static < T> Stream< T> stream(Tarray):返回一个流 重载形式,能够处理对应基本类型的数组:
- public static IntStream stream(int[]array)
- public static LongStream stream(long[] array)
- public static DoubleStream stream(double[] array)
// 创建Stream方式二: 通过数组
@Test
public void test3(){
// static <T> Stream<T> stream(Tarray):返回一个流
// int []arr = new int[](1,2,3,4,5,6);
// IntStream stream = Arrays.stream(arr);
Employee e1 =new Employee(1001,"马化腾",25,1000.4);
Employee employee = new Employee(1003, "刘强东", 38, 9000.4);
Employee[] employees = {e1, employee};
Stream<Employee> stream1 = Arrays.stream(employees);
}
2
3
4
5
6
7
8
9
10
11
# 方式三:通过Stream的of()
可以调用Stream类静态方法 of(),通过显示值创建一个流。它可以接收任意数量的参数。
- public static< T> Stream< T> of(T... values):返回一个流
// 创建Stream 方式四:创建无限流
@Test
public void test4(){
Stream<Integer> integerStream = Stream.of(1, 2, 3, 12);
// public static<T> Stream<T>iterate(final T seed, final UnaryOperator<T> f)·生成
// public static<T> Stream<T>generate(Supplier<T>s)
}
2
3
4
5
6
7
8
# 方式四:创建无限流
创建Stream方式四:创建无限流 可以使用静态方法 Stream.iterate()和 Stream.generate(),创建无限流。 ●迭代 public static< T> Stream< T>iterate(final T seed, final UnaryOperator< T> f)
生成
public static< T> Stream< T>generate(Supplier< T>s)
// 创建无限流
@Test
public void test5(){
// 遍历前10个偶数
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
// 生成
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
2
3
4
5
6
7
8
# Stream中间操作:
# 1、筛选切片
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。
filter(Predicate p) 接收Lambda,从流中排除某些元素
distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
limit(long maxsize) 截断流,使其元素不超过给定数量
skip(long n) 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与
、 limit(n)互补
// 1、筛选与切片
@Test
public void test1(){
List<Employee> employeeList = EmployeeData.getEmployees();
Stream<Employee> employeeStream = employeeList.stream();
// filter(Predicate p) 接收Lambda,从流中排除某些元素
employeeStream.filter(e->e.getSalary()>7000).forEach(System.out::println);
// limit(long maxsize) 截断流,使其元素不超过给定数量
employeeList.stream().limit(3).forEach(System.out::println);
System.out.println("----------");
employeeList.stream().skip(3).forEach(System.out::println);
// distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
employeeList.stream().distinct().forEach(System.out::println);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2、映射
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
map Tolnt( TolntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream。
map ToLong( ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
@Test
public void Test2(){
List<String> list =Arrays.asList("aaa","bbbb","cc");
// map(function f)
list.stream().map(String::toUpperCase).forEach(System.out::println);
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().map(Employee::getName)
.filter(name->name.length()>3).forEach(System.out::println);
// flatMap(Function f)
// flatMap(
// Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);
streamStream.forEach(s->s.forEach(System.out::println));
// 直接接受
list.stream().flatMap(StreamAPITest1::fromStringToStream).forEach(System.out::println);
}
public static Stream<Character> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for (Character c: str.toCharArray()){
list.add(c);
}
return list.stream();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 3、排序
sorted():产生一个新流,其中按自然顺序排序
sorted(Comparator com):产生一个新流,其中按比较器顺序排序
@Test
public void test3(){
// sorted():产生一个新流,其中按自然顺序排序
List<Integer> list = Arrays.asList(12, 43, 2, 56, 7, 84, 14);
list.stream().sorted().forEach(System.out::println);
EmployeeData.getEmployees().stream().sorted((e1,e2)->
{
int ageratum= Integer.compare(e1.getAge(),e2.getAge());
if (ageratum!=0){
return ageratum;
}else {
return Double.compare(e1.getSalary(),e2.getSalary());
}
}
)
.forEach(System.out::println);
EmployeeData.getEmployees().stream().sorted((e1,e2)->Integer.compare(e1.getAge(),e2.getAge()))
.forEach(System.out::println);
// sorted(Comparator com):产生一个新流,其中按比较器顺序排序
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 4、Stream的终止操作
终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List. Integer,甚至是void .
流进行了终止操作后,不能再次使用。1-匹配与查找
流进行了终止操作后,不能再次使用。
1-匹配与查找:
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 称为外部迭代。相反,Stream API使用内普迭代——它帮你把迭代做了)
public void test4() {
List<Employee> employees = EmployeeData.getEmployees();
// 任意员工的值都大于18
boolean match = employees.stream().allMatch(e -> e.getAge() > 30);
System.out.println(match);
// 是否存在员工工资大于10000
boolean b = employees.stream().anyMatch(e -> e.getSalary() > 10000);
System.out.println(b);
// 是否存在员工姓雷
boolean b1 = employees.stream().noneMatch(e -> e.getName().startsWith("1&"));
System.out.println(b1);
// 返回第一个元素
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first);
// 求个数
long count = employees.stream().filter(e -> e.getSalary() > 5000).count();
System.out.println("count = " + count);
Optional<Double> max = employees.stream().map(e -> e.getSalary()).max(Double::compare);
System.out.println("max = " + max);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 归约:
reduce(T iden, Binaryoperator b) 可以将流中元素反复结合起来,得到一个值。返回T
reduce(Binaryoperator b) 可以将流中元素反复结合起来,得到一个值。返回Optional< T>
备注:map 和reduce 的连接通常称为map-reduce模式,因Google用它来进行网络搜索而出名。
@Test
public void test(){
// 计算1-10的自然数的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println("reduce = " + reduce);
// 计算所有公司员工的工资的总和
List<Employee> employees = EmployeeData.getEmployees();
Stream<Double> doubleStream = employees.stream().map(Employee::getSalary);
Optional<Double> reduce1 = doubleStream.reduce(Double::sum);
System.out.println("reduce1 = " + reduce1);
}
2
3
4
5
6
7
8
9
10
11
12