标签:monkey lis tostring exist red 对象 格式转换 ring 表达式
public class LambdaDemo1{
// 定义接口
interface Printer{
void printer(String val);
}
// 定义一个打印方方法
public void printSomething(String something,Printer printer){
printer.printer(something);
}
public static void main(String[] args){
LambdaDemo1 lambdaDemo1 = new LambdaDemo1();
String something = "something";
// 传统写法
Printer printer = new Printer(){
@Override
public void printer(String val){
System.out.println("传统写法:"val);
}
};
printSomething(something,printer);
// lambda表达式 - 写法1
// lambda表达式用 -> 连接参数和方法体
// (String val) 参数 -- 左侧
// {} 方法体 -- 右侧
Printer printer = (String val) -> {
System.out.println("传统写法:"val);
};
printSomething(something,printer);
// lambda表达式 - 写法2
// 简写“写法1” -- 省略参数类型。
// lambda可根据定义的接口和上下文自动识别参数的类型
// 如果参数与类型不匹配会报错
Printer printer = (val) -> {
System.out.println("传统写法:"val);
};
printSomething(something,printer);
// lambda表达式 - 写法3
// 简写“写法2”
// 省略参数小括号:
// 如果只有一个参数,可省略参数外层的()
// 省略方法体花括号
// 如果方法体中只有一行代码,可省略方法体的{}
Printer printer = val -> System.out.println("传统写法:"val);
printSomething(something,printer);
// lambda表达式 - 写法4
// 简写“写法3”
// printSomething中的参数printer
// Printer printer = val -> System.out.println("传统写法:"val)
printSomething(something,val -> System.out.println("传统写法:"val));
}
}
// 1、集合转Stream
List<String> nameStrs = Arrays.asList("Monkey","Lion","Giraffe","Lemur");
List<String> sorted = nameStrs.stream() //
.filter(s -> s.startsWith("L")) // 过滤。判断条件:以字母"L"开头
.map(String::toUpperCase) // 将过滤到的元素,全部变成大写
.sorted() // 排序
.collect(toList()); // 组合成一个集合
// 2、数组转Stream
String[] players = {"kobe","james","curry","cyyt"};
Stream.of(players)
.filter(s -> s.startsWith("L"))
.map(String::toUpperCase)
.sorted()
.collect(toList());
// 3、HashSet转Stream
String[] players = {"kobe","james","curry","cyyt"};
Set<String> set = new HashSet<>(players);
List<String> sorted = set.stream() //
.filter(s -> s.startsWith("L")) // 过滤。判断条件:以字母"L"开头
.map(String::toUpperCase) // 将过滤到的元素,全部变成大写
.sorted() // 排序
.collect(toList()); // 组合成一个集合
// 4、行文本文件转Stream
Files.lines(Paths.get("file.txt"))
.filter(s -> s.startsWith("L")) // 过滤。判断条件:以字母"L"开头
.map(String::toUpperCase) // 将过滤到的元素,全部变成大写
.sorted() // 排序
.collect(toList()); // 组合成一个集合
public class Employee {
private Integer id;
private Integer age;
private String gender;
private String firstName;
private String lastName;
// 省略get set 构造
}
public class StreamFilterPredicate {
public static void main(String[] args){
Employee e1 = new Employee(1,20,"男","First1","Last1");
Employee e2 = new Employee(2,21,"女","First2","Last2");
Employee e3 = new Employee(3,24,"男","First3","Last3");
Employee e4 = new Employee(4,22,"男","First4","Last4");
Employee e5 = new Employee(5,21,"女","First5","Last5");
Employee e6 = new Employee(6,25,"男","First6","Last6");
Employee e7 = new Employee(7,23,"女","First7","Last7");
Employee e8 = new Employee(8,25,"男","First8","Last8");
Employee e9 = new Employee(9,26,"女","First9","Last9");
Employee e10 = new Employee(10,21,"男","First10","Last10");
List<Employee> employees = Arrays.asList(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10);
List<Employee> list = employees.stream()
// Predicate 谓语
// e.getAge() > 22 && e.getGender().equals("女") 谓词逻辑
.filter(e -> {e.getAge() > 22 && e.getGender().equals("女")})
.collect(Collectors.toList());
System.out.println(list);
}
}
谓词逻辑也可抽出来,复用
public class Employee {
private Integer id;
private Integer age;
private String gender;
private String firstName;
private String lastName;
// 省略get set 构造
public static Predicate<Employee> ageGreaterThan22 = x -> x.getAge() > 22;
public static Predicate<Employee> genderWoman = x -> x.getGender().equals("女");
}
public class StreamFilterPredicate {
public static void main(String[] args){
Employee e1 = new Employee(1,20,"男","First1","Last1");
Employee e2 = new Employee(2,21,"女","First2","Last2");
Employee e3 = new Employee(3,24,"男","First3","Last3");
Employee e4 = new Employee(4,22,"男","First4","Last4");
Employee e5 = new Employee(5,21,"女","First5","Last5");
Employee e6 = new Employee(6,25,"男","First6","Last6");
Employee e7 = new Employee(7,23,"女","First7","Last7");
Employee e8 = new Employee(8,25,"男","First8","Last8");
Employee e9 = new Employee(9,26,"女","First9","Last9");
Employee e10 = new Employee(10,21,"男","First10","Last10");
List<Employee> employees = Arrays.asList(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10);
List<Employee> list = employees.stream()
// 支持
// .and():并且
// .or():或者
// .negate():取反
.filter(Employee.ageGreaterThan22.and(Employee.genderWoman).negate())
.collect(Collectors.toList());
System.out.println(list);
}
}
public class StreamMap1 {
public static void main(String[] args){
List<String> alpha = Arrays.asList("Monkey", "Lion", "Giraffe", "Lemur");
//不使用Stream管道流
List<String> alphaUpper = new ArrayList<>();
for (String s : alpha) {
alphaUpper.add(s.toUpperCase());
}
System.out.println(alphaUpper); //[MONKEY, LION, GIRAFFE, LEMUR]
// 使用Stream管道流
List<String> collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList());
// "方法引用":String::toUpperCase。效果和s -> s.toUpperCase()效果一样
//List<String> collect = alpha.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
System.out.println(collect); //[MONKEY, LION, GIRAFFE, LEMUR]
}
}
// map()函数不仅可以处理数据,还可以转换数据的类型。如下:
Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
.mapToInt(String::length)
.forEach(System.out::println);
// 结果:
// 6
// 4
// 7
// 5
除了mapToInt。还有maoToLong,mapToDouble等等用法。
public class Employee {
private Integer id;
private Integer age;
private String gender;
private String firstName;
private String lastName;
// 省略get set 构造
}
public class StreamMap2 {
public static void main(String[] args){
Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
Employee e2 = new Employee(2,13,"F","Martina","Hengis");
Employee e3 = new Employee(3,43,"M","Ricky","Martin");
Employee e4 = new Employee(4,26,"M","Jon","Lowman");
Employee e5 = new Employee(5,19,"F","Cristine","Maria");
Employee e6 = new Employee(6,15,"M","David","Feezor");
Employee e7 = new Employee(7,68,"F","Melissa","Roy");
Employee e8 = new Employee(8,79,"M","Alex","Gussin");
Employee e9 = new Employee(9,15,"F","Neetu","Singh");
Employee e10 = new Employee(10,45,"M","Naveen","Jain");
List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
// 将每一个Employee的年龄增加一岁
// 将性别中的“M”换成“male”,F换成Female。
List<Employee> maped = employees.stream()
.map(e -> {
e.setAge(e.getAge() + 1);
e.setGender(e.getGender().equals("M")?"male":"female");
return e;
}).collect(Collectors.toList());
List<Employee> peeked = employees.stream()
.peek(e -> {
e.setAge(e.getAge() + 1);
e.setGender(e.getGender().equals("M")?"male":"female");
}).collect(Collectors.toList());
// .map()会return回一个新对象
// .peek()是特殊的map函数。对同一个对象操作。实现效果一样。
System.out.println(maped);
System.out.println(peeked);
}
}
// map可以对管道流中的数据进行转换操作,但是如果管道中还有管道,数组中还有数组该如何处理?
// 即:如何处理二维数组及二维集合类。
// 实现一个简单的需求:
// 将“hello”,“world”两个字符串组成的集合,元素的每一个字母打印出来。
// 如果不用Stream我们怎么写?写2层for循环,第一层遍历字符串,并且将字符串拆分成char数组,第二层for循环遍历char数组。
public class StreamFlatMap {
public static void main(String[] args){
List<String> words = Arrays.asList("hello", "word");
// .map():输出结果为:
// java.util.stream.ReferencePipeline$Head@3551a94
// java.util.stream.ReferencePipeline$Head@531be3c5
// 证明:
// 用map方法是做不到的,这个需求用map方法无法实现。
// map只能针对一维数组进行操作,数组里面还有数组,管道里面还有管道,它是处理不了每一个元素的。
words.stream()
.map(w -> Arrays.stream(w.split("")))
.forEach(System.out::println);
// .flatMap():输出结果为:
// h
// e
// l
// l
// o
// w
// o
// r
// d
// flatMap可以理解为将若干个子管道中的数据全都,平面展开到父管道中进行处理。
words.stream()
.flatMap(w -> Arrays.stream(w.split("")))
.forEach(System.out::println);
}
}
// distinct方法时,调用Object的equals方法进行对象的比较。
// 如果你有自己的比较规则,可以重写equals方法。
// 经过管道处理之后的数据是: ["Monkey", "Lion", "Giraffe", "Lemur"]
List<String> uniqueAnimals = Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
.distinct()
.collect(Collectors.toList());
// limt方法传入一个整数n,用于截取管道中的前n个元素。
// 经过管道处理之后的数据是:[Monkey, Lion]。
List<String> limitN = Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
.limit(2)
.collect(Collectors.toList());
// skip方法与limit方法的使用相反,用于跳过前n个元素,截取从n到末尾的元素。
// 经过管道处理之后的数据是: [Giraffe, Lemur]
List<String> skipN = Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
.skip(2)
.collect(Collectors.toList());
基本使用
// 默认的情况下,sorted是按照字母的自然顺序进行排序。
// 如下代码的排序结果是:[Giraffe, Lemur, Lion, Monkey]
// 字数按顺序G在L前面,L在M前面。第一位无法区分顺序,就比较第二位字母。
List<String> alphabeticOrder = Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
.sorted()
.collect(Collectors.toList());
像使用sql一样排序集合
排序器
// java8以前
Collections.sort();
// java8以后
List<T> list = Arrays.asList();
// Comparator<T> 排序器
list.sort(Comparator<T>);
// JDK默认定义的排序规则
// 例如:
// 大小写不敏感
list.sort(String.CASE_INSENSITIVE_ORDER);
// 自然顺序
list.sort(Comparator.naturalOrder());
对象排序
public class Employee {
private Integer id;
private Integer age;
private String gender;
private String firstName;
private String lastName;
// 省略get set 构造 toString()
}
public class SortList {
public static void main(String[] args){
Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
Employee e2 = new Employee(2,13,"F","Martina","Hengis");
Employee e3 = new Employee(3,43,"M","Ricky","Martin");
Employee e4 = new Employee(4,26,"M","Jon","Lowman");
Employee e5 = new Employee(5,19,"F","Cristine","Maria");
Employee e6 = new Employee(6,15,"M","David","Feezor");
Employee e7 = new Employee(7,68,"F","Melissa","Roy");
Employee e8 = new Employee(8,79,"M","Alex","Gussin");
Employee e9 = new Employee(9,15,"F","Neetu","Singh");
Employee e10 = new Employee(10,45,"M","Naveen","Jain");
List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
// 先是按性别的倒序排序,再按照年龄的倒序排序
employees.sort(
Comparator.comparing(Employee::getGender)
.thenComparing(Employee::getAge)
.reversed()
);
// 打印
employees.forEach(System.out::println);
// 与sql的区别:
// 都是正序 ,不加reversed
// 都是倒序,最后面加一个reserved
// 先是倒序(加reserved),然后正序
// 先是正序(加reserved,负负得正),然后倒序(加reserved)
}
}
// 如果我们只是希望将Stream管道流的处理结果打印出来,而不是进行类型转换。
// 我们就可以使用forEach()方法或forEachOrdered()方法。
Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
.parallel()
.forEach(System.out::println);
Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
.parallel()
.forEachOrdered(System.out::println); // 按顺序输出
// 通过Collectors.toSet()方法收集Stream的处理结果,将所有元素收集到Set集合中。
Set<String> collectToSet = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur", "Lion"
)
.collect(Collectors.toSet());
// 最终collectToSet 中的元素是:[Monkey, Lion, Giraffe, Lemur],注意Set会去重。
// 同样,可以将元素收集到List使用toList()收集器中。
List<String> collectToList = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur", "Lion"
).collect(Collectors.toList());
// 最终collectToList中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]
// 可以将数据元素收集到任意的Collection类型:即向所需Collection类型提供构造函数的方式。
LinkedList<String> collectToCollection = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur", "Lion"
).collect(Collectors.toCollection(LinkedList::new));
//最终collectToCollection中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]
// 注意:以上代码中使用了LinkedList::new,实际是调用LinkedList的构造函数,将元素收集到Linked List。
// 当然你还可以使用诸如LinkedHashSet::new和PriorityQueue::new将数据元素收集为其他的集合类型,这样就比较通用了。
// 通过toArray(String[]::new)方法收集Stream的处理结果,将所有元素收集到字符串数组中。
String[] toArray = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur", "Lion"
) .toArray(String[]::new);
//最终toArray字符串数组中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]
// Function.identity()方法,该方法很简单就是返回一个“ t -> t ”(输入就是输出的lambda表达式)
// distinct()来确保Map键值的唯一性
Map<String, Integer> toMap = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur", "Lion"
)
.distinct()
.collect(Collectors.toMap(
Function.identity(), // 元素输入就是输出,作为key
s -> (int) s.chars().distinct().count()// 元素的长度,作为value
));
// 最终toMap的结果是: {Monkey=6, Lion=4, Lemur=5, Giraffe=6}
Map<Character, List<String>> groupingByList = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur", "Lion"
)
.collect(Collectors.groupingBy(
s -> s.charAt(0) , // 根据元素首字母分组,相同的在一组
// counting() // 加上这一行代码可以实现分组统计
));
// 最终groupingByList内的元素: {G=[Giraffe], L=[Lion, Lemur, Lion], M=[Monkey]}
//如果加上counting() ,结果是: {G=1, L=3, M=1}
// 这是以上代码过程的说明:groupingBy第一个参数作为分组条件,第二个参数是子收集器。
// 判断管道中是否包含2,结果是: true
boolean containsTwo = IntStream.of(1, 2, 3).anyMatch(i -> i == 2);
// 统计元素个数:4
long nrOfAnimals = Stream.of(
"Monkey", "Lion", "Giraffe", "Lemur"
).count();
// 管道中元素数据累加结果:sum: 6
int sum = IntStream.of(1, 2, 3).sum();
//管道中元素数据平均值:average: OptionalDouble[2.0]
OptionalDouble average = IntStream.of(1, 2, 3).average();
//管道中元素数据最大值:max: 3
int max = IntStream.of(1, 2, 3).max().orElse(0);
// 全面的统计结果statistics: IntSummaryStatistics{count=3, sum=6, min=1, average=2.000000, max=3}
IntSummaryStatistics statistics = IntStream.of(1, 2, 3).summaryStatistics();
public class Employee {
private Integer id;
private Integer age;
private String gender;
private String firstName;
private String lastName;
// 省略get set 构造 toString()
}
public class MatchFind {
public static void main(String[] args){
Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
Employee e2 = new Employee(2,13,"F","Martina","Hengis");
Employee e3 = new Employee(3,43,"M","Ricky","Martin");
Employee e4 = new Employee(4,26,"M","Jon","Lowman");
Employee e5 = new Employee(5,19,"F","Cristine","Maria");
Employee e6 = new Employee(6,15,"M","David","Feezor");
Employee e7 = new Employee(7,68,"F","Melissa","Roy");
Employee e8 = new Employee(8,79,"M","Alex","Gussin");
Employee e9 = new Employee(9,15,"F","Neetu","Singh");
Employee e10 = new Employee(10,45,"M","Naveen","Jain");
List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
// 查找员工列表中是否包含年龄大于70的员工
// 传统写法
boolean isExistAgeThan70 = false;
for(Employee employee:employees){
if(employee.getAge() > 70){
isExistAgeThan70 = true;
break;
}
}
System.out.println(isExistAgeThan70);
// lambda写法
// .anyMatch():判断Stream流中是否包含某一个“匹配规则”的元素
// 只要包含一个“匹配规则”的元素,就返回true
isExistAgeThan70 = employees.steam().anyMatch(e -> e.getAge() > 70);
}
}
// .allMatch():判断是够Stream流中的所有元素都符合某一个"匹配规则"
// 所有元素都符合某一个"匹配规则",才返回true
boolean isExistAgeThan10 = employees.stream().allMatch(e -> e.getAge() > 10);
// 判断是否Stream流中的所有元素都不符合某一个"匹配规则"
// 所有元素都不符合某一个"匹配规则",才返回true
boolean isExistAgeLess18 = employees.stream().noneMatch(e -> e.getAge() < 18);
// findFirst用于查找第一个符合“匹配规则”的元素,返回值为Optional
// findAny用于查找任意一个符合“匹配规则”的元素,返回值为Optional
// 从列表中按照顺序查找第一个年龄大于40的员工。
Optional<Employee> employeeOptional
= employees.stream().filter(e -> e.getAge() > 40).findFirst();
System.out.println(employeeOptional.get());
// Optional类代表一个值存在或者不存在。在java8中引入,这样就不用返回null了。
// 如果存在,调用get()方法获取。
// 如果不存在,调用get()方法,抛出异常。
get()。如果存在,获取值。如果不存在,抛出异常。
isPresent() 方法。存在返回true,不存在返回false
boolean is = employees.stream().filter(e -> e.getAge() > 40).findFirst().isPresent();
System.out.println(is);
ifPresent(Consumer block)。会在值存在的时候执行给定的代码块。
employees.stream().filter(e -> e.getAge() > 40).findFirst().ifPresent(e -> System.out.println(e));
orElse。如果不存在值,给一个默认值
employees.stream().filter(e -> e.getAge() > 40).findFirst()
.orElse(new Employee(0,0,"F","",""));
Stream.reduce
,用来实现集合元素的归约.
reduce函数有三个参数:
// reduce初始值为0,累加器可以是lambda表达式,也可以是方法引用。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Integer total = numbers
.stream()
.reduce(0, (subtotal, element) -> subtotal + element);
System.out.println(total); //21
Integer result = numbers
.stream()
.reduce(0, Integer::sum);
System.out.println(result); //21
// 不仅可以归约Integer类型,只要累加器参数类型能够匹配,可以对任何类型的集合进行归约计算。
List<String> letters = Arrays.asList("a", "b", "c", "d", "e");
String res = letters
.stream()
.reduce("", (partialString, element) -> partialString + element);
System.out.println(res); // abcde
String result = letters
.stream()
.reduce("", String::concat);
System.out.println(result); // abcde
Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
Employee e2 = new Employee(2,13,"F","Martina","Hengis");
Employee e3 = new Employee(3,43,"M","Ricky","Martin");
Employee e4 = new Employee(4,26,"M","Jon","Lowman");
Employee e5 = new Employee(5,19,"F","Cristine","Maria");
Employee e6 = new Employee(6,15,"M","David","Feezor");
Employee e7 = new Employee(7,68,"F","Melissa","Roy");
Employee e8 = new Employee(8,79,"M","Alex","Gussin");
Employee e9 = new Employee(9,15,"F","Neetu","Singh");
Employee e10 = new Employee(10,45,"M","Naveen","Jain");
List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
// 计算每个员工的年龄之和
Integer total = employees.stream()
// 先用map将Stream流中的元素由Employee类型处理为Integer类型(age)。
.map(Employee::getAge)
// 然后对Stream流中的Integer类型进行归约
.reduce(0,Integer::sum);
System.out.println(total); //346
// 在进行并行流计算的时候,可能会将集合元素分成多个组计算。
// 为了更快的将分组计算结果累加,可以使用合并器。
Integer total2 = employees
// 并行流
.parallelStream()
// 获取每个员工年龄
.map(Employee::getAge)
// 对Stream流中的Integer类型进行归约
.reduce(0,Integer::sum,Integer::sum); //注意这里reduce方法有三个参数
System.out.println(total); //346
// 因为Stream流中的元素是Employee,累加器的返回值是Integer,所以二者的类型不匹配。
// 这种情况下可以使用Combiner合并器对累加器的结果进行二次归约,相当于做了类型转换。
Integer total3 = employees.stream()
.reduce(0,(totalAge,emp) -> totalAge + emp.getAge(),Integer::sum); //注意这里reduce方法有三个参数
System.out.println(total); //346
// 传统写法
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee em1, Employee em2) {
if(em1.getAge() == em2.getAge()){
return 0;
}
return em1.getAge() - em2.getAge() > 0 ? -1:1;
}
});
employees.forEach(System.out::println);
// lambda写法
employees.sort((em1,em2) -> {
if(em1.getAge() == em2.getAge()){
return 0;
}
return em1.getAge() - em2.getAge() > 0 ? -1:1;
});
employees.forEach(System.out::println);
本篇文章学习自 字母哥-《恕我直言:你可能真的不会JAVA系列》。
视频地址:
博客地址:
资料整理:
标签:monkey lis tostring exist red 对象 格式转换 ring 表达式
原文地址:https://www.cnblogs.com/luckyzs/p/13172453.html