@FunctionalInterface
public interface FunctionInterface<T,V> {
T apply (V value); // 只能有一个
static void apply1() {
System.out.println("这是静态方法");
}
static void apply2() {
System.out.println("这是静态方法");
}
default void apply3() {
System.out.println("这是默认方法");
}
}
Consumer<T>:消费型接口 void accept(T t)
Supplier<T>:供给型接口 T get()
Function<T, R>:函数型接口 R apply(T t)
Predicate<T>:断言型接口 boolean test(T t)
作用: lamda表达式实际上是对函数式接口编写匿名内部类的一种简写。
Runnable runnable = new Runnable() {
@Override
public void run() {
}
}; // 普通的匿名内部类的写法
Runnable runnable1 = () -> {
};// 使用lamda表达式实现
// 数组转化成stream的两种方式Arrays.stream和Stream.of
Integer[] ints = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Stream<Integer> stream = Arrays.stream(ints);
Stream<Integer> ints1 = Stream.of(ints);
// list集合转化成stream的方式
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
// map集合转化成stream的方式
HashMap<String, String> map = new HashMap<>();
Stream<Map.Entry<String, String>> stream = map.entrySet().stream();
Stream类常用方法分为两种:中间操作和终端操作。
中间操作:主要用于对数据处理,每次会返回一个新的流。
终端操作:每个流只能有一个终端操作,该终端操作会返回一个具体的结果。
Stream distinct(); 集合去重
@Data
@AllArgsConstructor
public class Person {
private String name;
private int age;
private List<Address> addr;
}
@Data
@AllArgsConstructor
public class Address {
private String attr1;
private String attr2;
}
List<Person> list = new ArrayList<Person>();
list.add(new Person("张三", 18, null));
list.add(new Person("张三", 18, null));
List<Person> result = list.stream()
.distinct()
.collect(Collectors.toList());
result.forEach(item -> System.out.println(item)); // 结果只有一条
Stream filter(Predicate super T> predicate); 对数据集合进行过滤
List<Person> list = new ArrayList<Person>();
list.add(new Person("张三", 18, null));
list.add(new Person("张三", 19, null));
List<Person> result = list.stream()
.filter(item -> item.getAge() > 18)
.collect(Collectors.toList());
result.forEach(item -> System.out.println(item)); // 过滤年龄小于19的数据
Stream map(Function super T, ? extends R> mapper); 将数据集合对象映射成任意对象的数据集合
List<Person> list = new ArrayList<Person>();
list.add(new Person("张三", 18, null));
list.add(new Person("张三", 19, null));
List<Integer> result = list.stream()
.map(item -> item.getAge())
.collect(Collectors.toList()); // 映射成integer对象
List<Address> result1 = list.stream()
.map(item -> item.getAddr())
.collect(Collectors.toList());// 映射成List对象
result.forEach(item -> System.out.println(item));
result1.forEach(item -> System.out.println(item));
Stream flatMap(Function super T, ? extends Stream extends R>> mapper); 返回一个stream对象,主要是将一个二维集合压缩成一个一维集合
List<String> list1 = Arrays.asList("a1","a2","a3");
List<String> list2 = Arrays.asList("b1","b2","b3");
List<List<String>> list = Arrays.asList(list1,list2);
list.stream().forEach(item -> System.out.println(item));
// 输出结果:[a1, a2, a3], [b1, b2, b3]
System.out.println("分割线2------------------");
list.stream()
.flatMap(item -> item.stream())
.forEach(item -> System.out.println(item));
// 输出结果:每个元素分别输出 a1, a2,a3,b1,b2,b3
Stream sorted(); 对元素进行排序
Stream sorted(Comparator super T> comparator);对元素进行排序,但是排序的对象必须制定排序规则,即实现Comparable接口
List<Person> list1 = new ArrayList<>();
list1.add(new Person("张三",18,null));
list1.add(new Person("李四",20,null));
list1.add(new Person("王五",19,null));
list1.add(new Person("赵六",19,null));
list1.stream()
.sorted((item1, item2) -> item1.getAge() - item2.getAge());
注意:Comparator接口提供了几个静态的方法来进行排序,我们可以使用其提供的方法来指定排序规则。
/*
1. comparing方法:指定排序字段,升序
2. reversed方法:翻转排序规则,转为降序
3. thenComparing方法:指定按前面指定排序后再按该字段排序
4. 5. 排序规则:以age字段降序排,再以name字段降序排
*/
List<Person> list1 = new ArrayList<>();
list1.add(new Person("张三",18,null));
list1.add(new Person("李四",20,null));
list1.add(new Person("王五",19,null));
list1.add(new Person("赵六",19,null));
list1.stream()
.sorted(Comparator.comparing(Person::getAge).reversed().thenComparing(Person::getName).reversed())
.forEach(item -> System.out.println(item));
Stream peek(Consumer super T> action);用于调试流执行操作过程,不会对元素进行任何改变
// peek方法就是进行调试用的,可以看到在流操作时每一个元素的执行情况
List<Person> list1 = new ArrayList<>();
list1.add(new Person("张三",18,null));
list1.add(new Person("李四",20,null));
list1.add(new Person("王五",19,null));
list1.add(new Person("赵六",19,null));
list1.stream()
.peek(item -> System.out.println("去重前" + item))
.distinct()
.peek(item -> System.out.println("过滤前" + item))
.filter(item -> item.getAge() > 18)
.peek(item -> System.out.println("映射前" + item))
.map(item -> item.getAge())
.forEach(item -> System.out.println(item));
Stream limit(long maxSize); 截取流元素前几个的数据,可与skip连用
Stream skip(long n);丢弃流元素前几个的数据,可与limit连用
List<Person> list1 = new ArrayList<>();
list1.add(new Person("张三",18,null));
list1.add(new Person("李四",20,null));
list1.add(new Person("王五",19,null));
list1.add(new Person("赵六",19,null));
list1.stream()
.distinct()
.filter(item -> item.getAge() > 18)
.map(item -> item.getAge())
.skip(1)
.limit(1)
.forEach(item -> System.out.println(item));
R collect(Collector super T, A, R> collector)收集器,将流转换为需要的对象
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
List<Person> list1 = list.stream().collect(Collectors.toList());
Map<Integer, String> map = list.stream().collect(Collectors.toMap(Person::getAge, Person::getName));
Set<Person> collect = list.stream().collect(Collectors.toSet());
void forEach(Consumer super T> action):遍历流里面的对象
Optional findFirst():返回流中的第一个元素
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
Person person = list.stream().findFirst().get();
Optional findAny():返回当前流中任意一个元素
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
Person person = list.stream().findAny().get();
long count():返回流中元素的个数
Optional max(Comparator super T> comparator): 根据比较规则返回最大值
Optional min(Comparator super T> comparator):根据比较规则返回最小值
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.stream().count();
list.stream().max(Comparator.comparing(Person::getAge));
list.stream().min(Comparator.comparing(Person::getAge));
boolean anyMatch(Predicate super T> predicate): 检查流中至少一个元素是否有匹配规则
boolean allMatch(Predicate super T> predicate): 检查流中所有元素是否匹配规则
boolean noneMatch(Predicate super T> predicate): 检查流中所有元素是否都不匹配规则
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.stream().anyMatch(value -> "zhangs".equals(value.getName()));
list.stream().allMatch(value -> "zhangs".equals(value.getName()));
list.stream().noneMatch(Value -> Value.getAge() == 18);
Optional reduce(BinaryOperator accumulator): 将流中的数据进行累积操作后返回
T reduce(T identity, BinaryOperator accumulator):同上述方法,多了带初始值
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
Optional<Integer> reduce = list.stream()
.map(Person::getAge)
.reduce((item1, item2) -> item1 + item2);
Integer reduce1 = list.stream()
.map(Person::getAge)
.reduce(15, (item1, item2) -> item1 + item2);
方法的引用是用来在特定情况下简化lamda表达式的一种写法,可以当成lamda表达式的语法糖
1.类::静态方法
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.stream().forEach(value -> System.out.println(value));
list.stream().forEach(System.out::println); // 类::静态方法
类::非静态方法
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build();
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build();
ArrayList<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.stream()
.map(item -> item.getAge())
.collect(Collectors.toList());
list.stream()
.map(Person::getAge) // 类::非静态方法
.collect(Collectors.toList());
对象::非静态方法
public class Student implements Comparator<Student>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
}
ArrayList<Student> students = new ArrayList<>();
Student student = new Student();
students.sort(student::compare);
类::new
public class Person {
private String name;
private int age;
public Person() {
}
public Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "name" + this.name + "age" + this.age;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String name;
private int age;
public Builder addName(String name) {
this.name = name;
return this;
}
public Builder addAge(int age) {
this.age = age;
return this;
}
public Person build(Function<Builder,Person> mapper ) {
return mapper.apply(this);
}
}
}
Person person1 = Person.builder()
.addName("zhangs")
.addAge(18)
.build(Person::new);// 类::new
Person person2 = Person.builder()
.addName("lisi")
.addAge(19)
.build(Person::new); // 类::new
/*
* flatmap将Person的addr属性(类型是List)压缩在一起,组成新的集合
* map是将原来的Person对象取addr属性和name属性映射成List 和String的集合
*/
List<Person> list3 = new ArrayList<>();
List<Address> addList = new ArrayList<>();
addList.add(new Address("test1","test1"));
addList.add(new Address("test2","test2"));
list3.add(new Person("张三",18,addList));
System.out.println("分割线------------------");
list3.stream()
.flatMap(item -> item.getAddr().stream())
.forEach(item -> System.out.println(item));
// 输出结果:
// Address(attr1=test1, attr2=test1)
// Address(attr1=test2, attr2=test2)
list3.stream()
.map(item -> item.getAddr())
.forEach(item -> System.out.println(item));
// 输出结果:
// [Address(attr1=test1, attr2=test1), Address(attr1=test2, attr2=test2)]
list3.stream()
.map(item -> item.getName())
.forEach(item -> System.out.println(item));
// 输出结果:
// 张三
/*
* 对于多层,可以多次使用flatMap方法来获取值
*/
List<String> list4 = Arrays.asList("c1","c2","c3");
List<String> list5 = Arrays.asList("d1","d2","d3");
List<List<String>> list6 = Arrays.asList(list4,list5);
List<List<List<String>>> list7 = Arrays.asList(list6);
list7.stream()
.flatMap(item -> item.stream())
.flatMap(item -> item.stream())
.forEach(item -> System.out.println(item));
// 输出结果: c1,c2,c3,d1,d2,d3
Integer[] ints = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
/*
只有一个参数,会返回Optional
*/
Optional<Integer> reduce1 = Arrays.stream(ints).reduce((item1, item2) -> {
System.out.println("参数3--" + item1);
System.out.println("参数4--" + item2);
Integer value = item1 + item2;
System.out.println("运行结果2 ----" + Thread.currentThread() + ":" + value);
return value;
});
/*
有两个参数,第一个参数相当于默认值参与运算
*/
Integer reduce2 = Arrays.stream(ints).reduce(777, (item1, item2) -> {
System.out.println("参数3--" + item1);
System.out.println("参数4--" + item2);
Integer value = item1 + item2;
System.out.println("运行结果2 ----" + Thread.currentThread() + ":" + value);
return value;
});
/*
有三个参数,但是使用的是串行流,第三个参数的方法是不会去执行的,也只有一个主进程,结果是正常的
*/
Integer reduce3 = Arrays.stream(ints)
.peek(value -> System.out.println(Thread.currentThread() + ":" + value))
.reduce(777, (item1, item2) -> {
System.out.println("参数1--" + item1);
System.out.println("参数2--" + item2);
Integer value = item1 + item2;
System.out.println("运行结果1 ----" + Thread.currentThread() + ":" + value);
return value;
}, (item1, item2) -> {
System.out.println("参数3--" + item1);
System.out.println("参数4--" + item2);
Integer value = item1 + item2;
System.out.println("运行结果2 ----" + Thread.currentThread() + ":" + value);
return value;
});
System.out.println(reduce3);
/*
有三个参数,用parallel()转成并行流,java会开启多个线程去将数据加载到不同线程中分别计算,
最后每个线程的结果在方法3里面进行累积,
此时会看到结果有问题,因为开启多个线程,导致每个线程都用了第一个参数的初始值,最终结果出了问题
因此需要注意在并行流里面需要考虑初始值对结果是否有影响
*/
Integer reduce4 = Arrays.stream(ints).parallel()
.peek(value -> System.out.println(Thread.currentThread() + ":" + value))
.reduce(777, (item1, item2) -> {
System.out.println("参数1--" + item1);
System.out.println("参数2--" + item2);
Integer value = item1 + item2;
System.out.println("运行结果1 ----" + Thread.currentThread() + ":" + value);
return value;
}, (item1, item2) -> {
System.out.println("参数3--" + item1);
System.out.println("参数4--" + item2);
Integer value = item1 + item2;
System.out.println("运行结果2 ----" + Thread.currentThread() + ":" + value);
return value;
});
System.out.println(reduce3);