Java8新特性
Stream流
Stream 是JDK1.8 中处理集合的关键抽象概念,Lambda 和 Stream 是JDK1.8新增的函数式编程最有亮点的特性了,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由**最终操作(terminal operation)**得到前面处理的结果。
Stream :非常方便精简的形式遍历集合实现 过滤、排序等。
Stream创建方式
public class Test01 {
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
/**
* user 对象属性值都是相等的 但是new 两个对象 这两个对象的 内存地址 是不一样的
*/
userEntities.add(new UserEntity("xiaowei", 16));
userEntities.add(new UserEntity("xiaowei", 16));
userEntities.forEach((t) -> {
System.out.println(t.toString());
});
System.out.println("重写UserEntity的equal方法后,将list集合通过stream转换为set集合后会自动去除重复...");
/**
* 创建stream方式两种
* 1.串行流stream() 单线程
* 2.并行流parallelStream() 多线程
* 并行流parallelStream 比串行流stream()效率要高的
*/
Stream<UserEntity> stream = userEntities.stream();
// 转换成set集合
Set<UserEntity> setUserList = stream.collect(Collectors.toSet());
setUserList.forEach(userEntity -> {
System.out.println(userEntity.toString());
});
}
}
class UserEntity {
private String userName;
private int age;
public UserEntity() {
}
public UserEntity(String userName, int age) {
this.userName = userName;
this.age = age;
}
public String getUserName() {
return userName;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "UserEntity{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
// @Override
public int hashCode() {
return userName.hashCode();
}
public boolean equals(Object obj) {
if (obj instanceof UserEntity)
return userName.equals(((UserEntity) obj).userName) && age == (((UserEntity) obj).age);
else
return false;
}
}
—————————-将list集合转换为map————————–
public class Test02 {
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
// list集合只有元素值 key list转换成map集合的情况下 指定key--user对象 username属性 value user对象
/**
* map<String(userName),UserEntity>
*/
Stream<UserEntity> stream = userEntities.stream();
/**
* new Function<UserEntity(list集合中的类型), String(key map)>
*/
Map<String, UserEntity> collect = stream.collect(Collectors.toMap(userEntity -> userEntity.getUserName(), userEntity -> userEntity));
collect.forEach((BiConsumer) (o, o2) -> System.out.println(o + "," + o2));
}
}
使用java.util.Arrays.stream(T[] array)方法用数组创建流
int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);
使用Stream的静态方法:of()、iterate()、generate()
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println); // 0 2 4 6 8 10
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);
Stream API
forEach
Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据。
public class TestTTTT {
public static void main(String[] args) {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
strings.stream().filter(s -> !s.isEmpty()).forEach(System.out::println);
}
}
结果:
abc
bc
efg
abcd
jkl
Process finished with exit code 0
map
接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
System.out.println(squaresList);
结果:
[9, 4, 49, 25]
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("xiaowei", 16));
userEntities.add(new UserEntity("xiaowei", 16));
List<String> list=null;
list= userEntities.stream().map(u -> u.getUserName()).collect(Collectors.toList());
System.out.println(list);
结果:
[mayikt, meite, zhangsan, xiaowei, xiaowei]
flatMap
接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
案例:将两个字符数组合并成一个新的字符数组。
class StreamTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("m-k-l-a", "1-3-5-7");
List<String> listNew = list.stream().flatMap(s -> {
// 将每个元素转换成一个stream
String[] split = s.split("-");
Stream<String> s2 = Arrays.stream(split);
return s2;
}).collect(Collectors.toList());
System.out.println("处理前的集合:" + list);
System.out.println("处理后的集合:" + listNew);
}
}
结果:
处理前的集合:[m-k-l-a, 1-3-5-7]
处理后的集合:[m, k, l, a, 1, 3, 5, 7]
Process finished with exit code 0
filter
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
System.out.println(count);
结果:
2
public class Test14 {
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
userEntities.add(new UserEntity("mayikt", 12));
// where userName='mayikt' and age>18
Stream<UserEntity> stream = userEntities.stream();
stream.filter(userEntity -> "mayikt".equals(userEntity.getUserName()) && userEntity.getAge() > 18)
.forEach((userEntity -> System.out.println(userEntity)));
}
}
结果:
UserEntity{userName='mayikt', age=20}
Process finished with exit code 0
limit
limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 3 条数据:
List<String>str1 = Arrays.asList("abc", "bc", "efg", "abcd", "jkl");
str1.stream().limit(3).forEach(System.out::println);
结果:
abc
bc
efg
sorted
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
案例:
public class StreamTest {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
personList.add(new Person("Tom", 8900, 22, "male", "Washington"));
personList.add(new Person("Jack", 9000, 25, "male", "Washington"));
personList.add(new Person("Lily", 8800, 26, "male", "New York"));
personList.add(new Person("Alisa", 9000, 26, "female", "New York"));
// 按工资增序排序
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).reversed())
.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);
}
}
结果:
按工资自然排序:[Lily, Tom, Sherry, Jack, Alisa]
按工资降序排序:[Sherry, Jack, Alisa,Tom, Lily]
先按工资再按年龄自然排序:[Sherry, Jack, Alisa, Tom, Lily]
先按工资再按年龄自定义降序排序:[Alisa, Jack, Sherry, Tom, Lily]
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("打印列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining("+"));
System.out.println("合并字符串: " + mergedString);
结果:
打印列表: [abc, bc, efg, abcd, jkl]
合并字符串: abc+bc+efg+abcd+jkl
统计1
List<Integer> num = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = num.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
結果:
列表中最大的数 : 7
列表中最小的数 : 2
所有数之和 : 25
平均数 : 3.5714285714285716
List<Double> num = Arrays.asList(3.00, 2.00, 2.00, 3.00, 7.00, 3.00, 5.00);
DoubleSummaryStatistics stats = num.stream().mapToDouble((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
結果:
列表中最大的数 : 7.0
列表中最小的数 : 2.0
所有数之和 : 25.0
平均数 : 3.5714285714285716
public class Test11 {
public static void main(String[] args) {
Stream<Integer> integerStream = Stream.of(10, 50, 30, 10);
Optional<Integer> reduce = integerStream.reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer a1, Integer a2) {
return a1 + a2;
}
});
System.out.println(reduce.get());
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
Optional<UserEntity> sum = stream.reduce((user1, user2) -> {
UserEntity userEntity = new UserEntity("sum", user1.getAge() + user2.getAge());
return userEntity;
});
System.out.println(sum.get());
System.out.println(sum.get().getAge());
}
}
结果:
100
UserEntity{userName='sum', age=163}
163
Process finished with exit code 0
public class Test12 {
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
Optional<UserEntity> min = stream.min((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(min.get());
}
}
结果:
UserEntity{userName='wangmazi', age=19}
Process finished with exit code 0
统计2
Collectors
提供了一系列用于数据统计的静态方法:
- 计数:
count
- 平均值:
averagingInt
、averagingLong
、averagingDouble
- 最值:
maxBy
、minBy
- 求和:
summingInt
、summingLong
、summingDouble
- 统计以上所有:
summarizingInt
、summarizingLong
、summarizingDouble
class StreamTest {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, 23, "male", "New York"));
personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
// 求总数
Long count = personList.stream().collect(Collectors.counting());
// 求平均工资
Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
// 求最高工资
Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
// 求最低工资
Optional<Integer> min = personList.stream().map(Person::getSalary).collect(Collectors.minBy(Integer::compare));
// 求工资之和
Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
//Integer sum = personList.stream().map(e->e.getSalary()).collect(Collectors.summingInt(e->e));
// 一次性统计所有信息
DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println("员工总数:" + count);
System.out.println("员工平均工资:" + average);
System.out.println("员工最高工资:" + max.get());
System.out.println("员工最低工资:" + min.get());
System.out.println("员工工资总和:" + sum);
System.out.println("员工工资所有统计:" + collect);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Person{
private String name;
private Integer salary;
private Integer age;
private String sex;
private String city;
}
结果:
员工总数:3
员工平均工资:7900.0
员工最高工资:8900
员工最低工资:7000
员工工资总和:23700
员工工资所有统计:DoubleSummaryStatistics{count=3, sum=23700.000000, min=7000.000000, average=7900.000000, max=8900.000000}
Process finished with exit code 0
Match
- anyMatch表示,判断的条件里,任意一个元素成功,返回true
- allMatch表示,判断条件里的元素,所有的都是,返回true
- noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
public class Test13 {
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
Stream<UserEntity> stream = userEntities.stream();
boolean b = stream.allMatch(userEntity -> "mayikt".equals(userEntity.getUserName()));
System.out.println(b);
}
}
结果:
false
Process finished with exit code 0
聚合(max/min/count)
案例一:获取String
集合中最长的元素。
public class StreamTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
Optional<String> max = list.stream().max(Comparator.comparing(String::length));
System.out.println("最长的字符串:" + max.get());
}
}
结果:
最长的字符串:weoujgsd
案例二:获取Integer
集合中的最大值
public class Stream {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);
// 自然排序
Optional<Integer> max = list.stream().max(Integer::compareTo);
// 1自定义排序
Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
// 2自定义排序
Optional<Integer> max3 = list.stream().max((e1,e2)->e1.compareTo(e2));
System.out.println("自然排序的最大值:" + max.get());
System.out.println("1自定义排序的最大值:" + max2.get());
System.out.println("2自定义排序的最大值:" + max3.get());
}
}
自然排序的最大值:11
1自定义排序的最大值:11
2自定义排序的最大值:11
Process finished with exit code 0
案例三:获取员工工资最高的人。
public class StreamTest {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, 23, "male", "New York"));
personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
personList.add(new Person("Anni", 8200, 24, "female", "New York"));
personList.add(new Person("Owen", 9500, 25, "male", "New York"));
personList.add(new Person("Alisa", 7900, 26, "female", "New York"));
Optional<Person> max = personList.stream().max(Comparator.comparingInt(Person::getSalary));
System.out.println("员工工资最大值:" + max.get().getSalary());
}
}
员工工资最大值:9500
案例四:计算Integer
集合中大于6的元素的个数。
import java.util.Arrays;
import java.util.List;
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
long count = list.stream().filter(x -> x > 6).count();
System.out.println("list中大于6的元素个数:" + count);
}
}
list中大于6的元素个数:4
joining
joining
可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
public class StreamTest {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Tom", 8900, 23, "male", "New York"));
personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(","));
System.out.println("所有员工的姓名:" + names);
List<String> list = Arrays.asList("A", "B", "C");
String string = list.stream().collect(Collectors.joining("-"));
System.out.println("拼接后的字符串:" + string);
}
}
结果:
所有员工的姓名:Tom,Jack,Lily
拼接后的字符串:A-B-C
Lambda表达式
Java8中的接口
在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的,这些修饰符都是默认的。
接口定义方法:public 抽象方法 需要子类实现
接口定义变量:public、static、final
在JDK 1.8开始 支持使用static和default 修饰 可以写方法体,不需要子类重写。
方法:
普通方法:可以有方法体
抽象方法 :没有方法体需要子类实现 重写。
public interface JDK8Interface {
//抽象方法
void addOrder();
//默认方法 可以写方法体
default void getDefaultOrder() {
System.out.println("我是默认方法 我可以写方法体");
}
//静态方法 可以写方法体
static void getStaticOrder() {
System.out.println("我是静态的方法 可以写方法体");
}
}
public class JDK8InterfaceImpl implements JDK8Interface {
/**
* 默认和静态方法不是我们的抽象方法 ,所以不需要重写
*/
@Override
public void addOrder() {
System.out.println("addOrder");
}
}
Lambda表达式
先定义一个接口:
public interface OrderService {
void get();
/**
* 如果需要使用到OrderService接口
* 接口是无法new、可以通过匿名内部类new
* 定义子类
*/
}
调用接口:
public class Test02 {
public static void main(String[] args) {
// 1.使用new的实现类的形式调用接口
OrderService orderSerivce1 = new OrderSerivceImpl();
orderSerivce1.get();
//2.使用匿名内部类的形式调用OrderService 中get方法
OrderService orderService = new OrderService() {
//--------------这个注解也可以不写-------------------
@Override
public void get() {
System.out.println("get");
}
};
orderService.get();
//或者直接:
new OrderService() {
@Override
public void get() {
System.out.println("get");
}
}.get();
//3.使用lambda调用接口
OrderService orderService= () -> {
System.out.println("get")
};
orderService.get();
//简化:
((OrderService) () -> System.out.println("get")).get();
//4.创建一个线程
new Thread(() -> System.out.println(Thread.currentThread().getName() + ",run")).start();
}
}
Lambda表达式的规范
使用Lambda表达式 依赖于函数接口
在接口中只能够允许有一个抽象方法
在函数接口中定义object类中方法 (在函数接口中可以有继承于object类的方法 )
使用默认或者静态方法
@FunctionalInterface 表示该接口为函数接口
Java中的Lambda表达式的规范,必须是为函数接口。
函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口
JDK中自带的函数接口:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
我们也可以使用@FunctionalInterface修饰为函数接口
函数接口的定义
在接口中只能有一个抽象方法
@FunctionalInterface 标记为该接口为函数接口
可以通过default 修饰为普通方法
可以定义object类中的方法
@FunctionalInterface
public interface MyFunctionalInterface {
void get();
default void defaultAdd() {
System.out.println("我是默认的方法");
}
/**
* object父类中的方法可以在函数接口中重写
*/
String toString();
}
可以理解为lambda就是重写实现了函数接口中的抽象方法,从而快速直接通过接口调用方法
Lambda表达式的语法
无参方法调用
public interface AcanthopanaxInterface {
void get();
}
AcanthopanaxInterface acanthopanaxInterface = () -> {
System.out.println("使用lamdba表达式调用方法");
};
acanthopanaxInterface.get();
带参数和返回值
@FunctionalInterface
public interface YouShenInterface {
String get(int i, int j);
}
public class Test04 {
public static void main(String[] args) {
// 1.使用匿名内部类调用有参数函数方法
// String result = new YouShenInterface() {
// @Override
// public String get(int i, int j) {
// return i + "-" + j;
// }
// }.get(1, 1);
// System.out.println(result);
//2.使用lamdba 调用有参数函数方法,不用写参数类型
YouShenInterface youShenInterface = (i, j) -> {
System.out.println("mayikt:" + i + "," + j);
return i + "-" + j;
};
System.out.println(youShenInterface.get(1, 1));
}
}
精简语法
// 1.精简写法优化 如果方法体中只有一条语句的情况下 可以不需要写{}
// AcanthopanaxInterface acanthopanaxInterface = () -> {
// System.out.println("mayikt");
// };
// acanthopanaxInterface.get();
AcanthopanaxInterface acanthopanaxInterface2 = () ->
System.out.println("mayikt");
acanthopanaxInterface2.get();
;
// 2.如果方法体只有一条return的情况下不需要些{} 和return
// YouShenInterface youShenInterface = (i, j) -> {
// return i + "-" + j;
// };
// 优化后
YouShenInterface youShenInterface2 = (i, j) -> i + "-" + j;
System.out.println(youShenInterface2.get(1, 2));
//((YouShenInterface)(i,j)-> i + "--" + j).get(1,2);
Lambda实例
遍历集合
Foreach:
ArrayList<String> strings = new ArrayList<>();
strings.add("mayikt");
strings.add("xiaowei");
strings.add("xiaomin");
// strings.forEach(new Consumer() {
//----------------函数接口:Consumer()
// @Override
// public void accept(Object o) {
// System.out.println("o:" + o);
// }
// });
strings.forEach((o) -> {
System.out.println(o);
});
集合排序
public class UserEntity {
private String name;
private Integer age;
public UserEntity(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
ArrayList<UserEntity> userlists = new ArrayList<>();
userlists.add(new UserEntity("mayikt", 22));
userlists.add(new UserEntity("xiaomin", 18));
userlists.add(new UserEntity("xiaoha", 36));
// userlists.sort(new Comparator<UserEntity>() {
//---------------Comparator<UserEntity>()是一个函数接口
// @Override
// public int compare(UserEntity o1, UserEntity o2) {
// return o1.getAge() - o2.getAge();
// }
// });
userlists.sort((o1, o2) ->
o1.getAge() - o2.getAge()
);
userlists.forEach((Consumer) o -> System.out.println("o:" + o.toString()));
结果:通过年龄排序
UserEntity{userName='xiaoxiao', age=6}
UserEntity{userName='xiaomin', age=12}
UserEntity{userName='xiaojun', age=23}
Process finished with exit code 0
List转换为Map
public class Test02 {
public static void main(String[] args) {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
// list集合只有元素值 key list转换成map集合的情况下 指定key--user对象 username属性 value user对象
/**
* map<String(userName),UserEntity>
*/
Stream<UserEntity> stream = userEntities.stream();
/**
* new Function<UserEntity(list集合中的类型), String(key map)>
*/
Map<String, UserEntity> collect = stream.collect(Collectors.toMap(userEntity -> userEntity.getUserName(), userEntity -> userEntity));
collect.forEach((BiConsumer) (o, o2) -> System.out.println(o + "," + o2));
}
}
结果:
mayikt,UserEntity{userName='mayikt', age=20}
zhangsan,UserEntity{userName='zhangsan', age=35}
meite,UserEntity{userName='meite', age=28}
Process finished with exit code 0
方法引入
方法引用其实也离不开Lambda表达式, 需要结合lambda表达式能够让代码变得更加精简。
- 静态方法引入 类名::(静态)方法名称
- 对象方法引入 类名:: 实例方法名称
- 实例方法引入 new对象 对象实例::方法引入
- 构造函数引入 类名::new
类型 | 语法 | 对应的Lambda表达式 |
---|---|---|
静态方法引用 | 类名::staticMethod | (args) ->类名.staticMethod(args) |
实例方法引用 | inst::instMethod | (args) ->inst.instMethod(args) |
对象方法引用 | 类名::instMethod | (inst,args) ->类名.instMethod(args) |
构建方法引用 | 类名::new | (args) ->new 类名(args) |
需要遵循一个规范:
引入的方法参数列表、返回类型与函数接口参数列表、返回类型必须要保持一致(对象方法除外)。
方法引入实际上就是lambda表达式中直接引入的方法。
静态方法的引入
举个栗子:
public class Method {
public static void main(String[] args) {
// 1.使用匿名内部类的形式 重写get方法,引入静态方法getStaticMethod
new MessageInterface() {
@Override
public void get(Integer a) {
Method.getStaticMethod(a);
}
}.get(10);
//2.Lambda表达式中引入静态方法:
MessageInterface messageInterface2 = (a) -> {
Method.getStaticMethod(a);
};
messageInterface2.get(8);
//静态方法引入可以理解为在Lambda表达式中引入一个静态方法,去实现函数接口中的抽象方法,然后就可以调用接口中 //的这个方法,其实实际执行的是引入的方法.
//使用方法引入调用方法 必须满足:方法引入的方法必须和函数接口中的方法参数列表/返回值一定保持一致。
//静态方法getStaticMethod的返回值类型(都是void)和参数列表(都是Integer a)一致,符合方法引入的规范
//简化:
MessageInterface messageInterface = Method::getStaticMethod;
messageInterface.get(6);
}
/**
* Method的静态方法
*/
public static void getStaticMethod(Integer a) {
System.out.println("我是静态方法-a的值为:"+a);
}
}
//函数接口:
@FunctionalInterface
public interface MessageInterface {
void get(Integer a);
}
结果:
我是静态方法-a的值为:10
我是静态方法-a的值为:8
我是静态方法-a的值为:6
Process finished with exit code 0
实例方法的引入
public class Test009 {
public static void main(String[] args) {
Test009 test009 = new Test009();
//1.匿名内部类的写法
MessageInterface messageInterface1 = new MessageInterface() {
@Override
public void get(Integer a) {
test009.getT(a);
}
};
messageInterface1.get(1);
//2.Lambda的写法
MessageInterface messageInterface = (a) -> {
test009.getT(a);
};
messageInterface.get(2);
//3.实例方法引入
MessageInterface messageInterface2 = test009::getT;
messageInterface2.get(1);
}
public void getT (Integer a){
System.out.println("实例方法引入---get方法:" + a);
}
}
//函数接口:
@FunctionalInterface
public interface MessageInterface {
void get(Integer a);
}
结果:
实例方法引入---get方法:1
实例方法引入---get方法:2
实例方法引入---get方法:1
Process finished with exit code 0
构造方法的引入
public class Test011 {
public static void main(String[] args) {
// UserInterface userInterface = () -> new UserEntity();
UserInterface UserInterface2= UserEntity::new;
UserInterface2.getUser();//调用无参构造,生成一个UserEntity
}
}
public class UserEntity {
private String userName;
private int age;
public UserEntity() {
}
//函数接口:
public interface UserInterface {
UserEntity getUser();
}
对象方法的引入
🎈🎈函数接口中抽象方法的参数是对象
public static void main(String[] args) {
// 1.使用匿名内部类的形式
MayiktService mayiktService = new MayiktService() {
@Override
public String get(Test23 t) {
return t.objGet();
}
};
System.out.println(mayiktService.get(new Test23()));
// 2.Lambda t表示对象引用
MayiktService mayiktService1 = (t) -> t.objGet();
System.out.println(mayiktService1.get(new Test23()));
// 3.方法引入 在这时候我们函数接口 第一个参数传递test23 返回调用test23.objGet方法
MayiktService mayiktService2 = Test23::objGet;
System.out.println(mayiktService2.get(new Test23()));//执行的是Test23的objGet方法
//Test23::objGet;----- (t) -> t.objGet();
// Function中的抽象方法: R apply(T t); T apply方法传递的参数类型 : R apply 方法返回的类型
// 需要将string类型字符串获取长度
//Function<String, Integer> strFunction = (str) -> {
// return str.length();
// };
Function<String, Integer> function2 = String::length;
System.out.println(function2.apply("sovzn"));//执行的是String的length方法
}
public String objGet() {
return "shiyaochang";
}
}
//函数接口:
public interface MayiktService {
String get(Test23 test23);
}
结果:
shiyaochang
shiyaochang
shiyaochang
5
Process finished with exit code 0
遍历map
public class Map {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("name1", "张三");
map.put("name2", "李四");
map.put("name3", "王五");
map.put("name4", "赵六");
map.forEach((k, v) ->
System.out.println(k)
);
map.forEach((k, v) ->
System.out.println(v)
);
map.forEach((k, v) ->
System.out.println(k + ":" + v)
);
}
}
name4
name3
name2
name1
赵六
王五
李四
张三
name4:赵六
name3:王五
name2:李四
name1:张三
Process finished with exit code 0
- Post link: http://sovzn.github.io/2021/07/19/Java8%E6%96%B0%E7%89%B9%E6%80%A7/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues