四种函数式接口用来调用
消费者,消费数据
public interface Consumer<T> {
void accept(T t);
}
供应商,给我们产生数据
public interface Supplier<T> {
T get();
}
断言,判断传入的t是不是满足条件
public interface Predicate<T> {
boolean test(T t)
}
函数,就是将一个数据转化成另一个数据
public interface Function<T, R> {
R apply(T t);
}
做功能判断
isPresent()方法用于判断包装对象的值是否非空
做功能
ifPresent() 方法接受一个Consumer对象(消费函数)
{一个判断,一个消费 这种函数式接口简直完美}
orElse() 方法功能比较简单,即如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)
orElseGet() 方法与orElse()方法类似,区别在于orElseGet()方法的入参为一个Supplier对象,用Supplier对象的get()方法的返回值作为默认值
orElseThrow() 方法其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常,并在orElseThrow()中将异常抛出
JDK1.8函数式编程Stream
Stream流的创建方式
1、集合转化(ArrayList,LinkedList没有map )map不是collection的子类
2、数组转化
3、静态方法调用,合并流,数组生成
public class StreamCreate {
/**
* 三种创建方式
* 1,对List进行Stream
* 2.对数组进行转化
* 3.调用静态方法
*
*/
public static void main(String[] args) {
//数组集合转换
List<Integer> list = new ArrayList<>();
list.add(1);
Stream<Integer> stream = list.stream();
//链表集合转换
LinkedList<Integer> list2 = new LinkedList<>();
list2.add(2);
Stream<Integer> stream2 = list2.stream();
//数组转换
List<Integer> list3 = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream<Integer> stream3 = list3.stream();
//合流
Stream<Integer> concat = Stream.concat(stream, stream2);
//调用静态方法
Stream<Double> random =Stream.generate(Math::random).limit(3);
}
}
Stream一些常用api
终止操作
(1)遍历/匹配(foreach/find/match)
(2)归集(toList/toSet/toMap)
(3) 统计(count/averaging/sum/max/min)
(4)归约(reduce)
(5)接合(joining)
(6)分组(partitioningBy 分成两个区/groupingBy)
/**
* 终止操作
*/
public class terminationLambdaTest {
List<Person> personList = new ArrayList<>();
List<Integer> simpleList = Arrays.asList(15, 22, 9, 11, 33, 52, 14);
@Before
public void initData(){
personList.add(new Person("张三",3000,23,"男","太原"));
personList.add(new Person("李四",7000,34,"男","西安"));
personList.add(new Person("王五",5200,22,"女","太原"));
personList.add(new Person("小黑",1500,33,"女","上海"));
personList.add(new Person("狗子",8000,44,"女","北京"));
personList.add(new Person("铁蛋",6200,36,"女","南京"));
}
@Test
/** 遍历/匹配(foreach/find/match)
*
*/
public void foreachTest(){
simpleList.stream().forEach(System.out::println);
simpleList.forEach(System.out::println);
}
@Test
public void findTest(){
//打印第一个
Optional<Integer> first = simpleList.stream().findFirst();
//高并发下随便打印一个
Optional<Integer> any = simpleList.parallelStream().findFirst();
System.out.println("first = " + first);
System.out.println("any = " + any);
}
@Test
public void allMatchTest(){
boolean flag = personList.stream().allMatch(p -> {
boolean b = p.getAge() > 2000;
return b;
});
System.out.println("flag = " + flag);
}
@Test
public void anyMatchTest(){
boolean flag = personList.stream().anyMatch(p -> {
boolean b = p.getAge() > 2000;
return b;
});
System.out.println("flag = " + flag);
}
@Test
/**
* 归集(toList/toSet/toMap)
*/
public void collectTest(){
//重新装填
List<Integer> collect = simpleList.stream().collect(Collectors.toList());
System.out.println(collect);
Set<Integer> collectSet = simpleList.stream().collect(Collectors.toSet());
System.out.println(collectSet);
Map<Integer,Integer> collectMap = simpleList.stream().collect(Collectors.toMap(item->item,item->item+1));
System.out.println(collectMap);
}
@Test
public void countTest(){
/** 统计
* 数组随机统计个数,求平均,求和
*/
long count = new Random().ints().limit(20).count();
System.out.println("count = " + count);
OptionalDouble average = new Random().ints().limit(50).average();
average.ifPresent(System.out::println);
int sum = new Random().ints().limit(50).sum();
System.out.println(sum);
}
@Test
public void reduceTest(){
/**
* 规约
* 将流进行缩减求乘积,最值,求和
*/
Integer reduce = simpleList.stream().reduce(1, (n1, n2) -> n1 * n2);
System.out.println("reduce = " + reduce);
//初始值 1,结果 n1,循环的具体数n2
Integer reduce2 = simpleList.stream().reduce(1, (n1, n2) -> n1 +n2);
System.out.println("reduce2 = " + reduce2);
}
/**
* 接合(joining)
* joining可以将Stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
*/
@Test
public void joiningTest(){
List<String> list = Arrays.asList("A", "B", "C");
String string = list.stream().collect(Collectors.joining("==="));
System.out.println("拼接后的字符串:" + string);
}
/**
* 分组(partitioningBy/groupingBy)
* 分区:将stream按条件分为两个Map,比如员工按薪资是否高于5000分为两部分。
* 分组:将集合分为多个Map,比如员工按性别分组。
*/
@Test
public void groupingByTest(){
// 将员工按薪资是否高于5000分组
Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 5000));
// 将员工按性别分组
Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
// 将员工先按性别分组,再按地区分组
Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
System.out.println("员工按薪资是否大于5000分组情况:" + part);
System.out.println("员工按性别分组情况:" + group);
System.out.println("员工按性别、地区:" + group2);
}
}
中间操作
(1)筛选(filter)
(2)映射(map/flatMap)
(3)排序(sorted)
(4)peek操作
(5)其他操作
流也可以进行合并、去重、限制、跳过等操作。
/**
* 中间操作
*/
public class middleLambdaLambdaTest {
List<Person> personList = new ArrayList<>();
List<Integer> simpleList = Arrays.asList(11,11,22,22,11,23,43,55,78);
@Before
public void initData(){
personList.add(new Person("张三",3000,23,"男","太原"));
personList.add(new Person("李四",7000,34,"男","西安"));
personList.add(new Person("王五",5200,22,"女","太原"));
personList.add(new Person("小黑",1500,33,"女","上海"));
personList.add(new Person("狗子",8000,44,"女","北京"));
personList.add(new Person("铁蛋",6200,36,"女","南京"));
}
// (1)筛选(filter)
@Test
public void filterTest(){
simpleList.stream().filter(item -> item > 17).forEach(System.out::println);
List<Person> collect = personList.stream().filter(item -> item.getSalary() > 8000).collect(Collectors.toList());
System.out.println("collect = " + collect);
}
// (2)映射(map/flatMap)
@Test
public void mapTest(){
personList.stream().map(item -> {
item.setSalary(item.getSalary()+1000);
return item;
}).forEach(System.out::println);
List<String> collect = simpleList.stream().map(num -> Integer.toString(num))
.collect(Collectors.toList());
System.out.println("collect = " + collect);
}
// (3)排序(sorted)
@Test
public void sortTest(){
// 按工资升序排序(自然排序)
List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
.collect(Collectors.toList());
// 按工资倒序排序
List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
.map(Person::getName).collect(Collectors.toList());
// 先按工资再按年龄升序排序
List<String> newList3 = personList.stream()
.sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
.collect(Collectors.toList());
// 先按工资再按年龄自定义排序(降序)
List<String> newList4 = personList.stream().sorted((p1, p2) -> {
if (p1.getSalary() == p2.getSalary()) {
return p2.getAge() - p1.getAge();
} else {
return p2.getSalary() - p1.getSalary();
}
}).map(Person::getName).collect(Collectors.toList());
System.out.println("按工资升序排序:" + newList);
System.out.println("按工资降序排序:" + newList2);
System.out.println("先按工资再按年龄升序排序:" + newList3);
System.out.println("先按工资再按年龄自定义降序排序:" + newList4);
}
// (4)peek操作
@Test
public void peekTest(){
// 在stream中间进行调试,因为stream不支持debug
List<Person> collect = personList.stream().filter(p -> p.getSalary() > 5000)
.peek(System.out::println).collect(Collectors.toList());
// 修改元素的信息,给每个员工涨工资一千
personList.stream().peek(p -> p.setSalary(p.getSalary() + 1000))
.forEach(System.out::println);
}
// (5)其他操作
// 流也可以进行合并、去重、限制、跳过等操作。
@Test
public void otherTest(){
// distinct去掉重复数据
// skip跳过几个数据
// limit限制使用几个数据
simpleList.stream().distinct().skip(2).limit(3).forEach(System.out::println);
}
// 11,11,22,22,11,23,43,55,78
// 去重 11,22,23,43,55,78
// 掉过两个 23,43,55,78
// 使用3个 23,43,55
@Test
//练习题 分别求男女员工的最高工资
public void practiceTest() {
Map<String, Integer> map = new HashMap<>();
Map<String, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(Person::getSex));
for (Map.Entry<String, List<Person>> Entry : collect.entrySet()) {
String key=Entry.getKey();
Integer value=Entry.getValue().stream().mapToInt(Person::getSalary).max().orElse(0);
//mapToInt保存为单一的工资
map.put(key,value);
}
System.out.println(map);
}
}