JDK8新特性简介、Lambda表达式、Stream流常用api介绍
接口
- Java1.8前接口中是不允许有普通方法的,在Java1.8后允许接口中有普通方法,只需要加上default关键字即可;
- Java1.8后可以使用static和default修饰方法后,可以存在方法体。
代码
public interface UserService {
/**
* 新增
* @param name 用户名
* @param age 年龄
*/
void insert(String name,Integer age);
/**
* 更新
* @param name
* @return
*/
default String update(String name){
return "success";
}
/**
* 查询
* @return
*/
static String select(){
System.out.println("五月天");
return "加入五月天永远不会太迟";
};
}
函数式接口
接口中只定义了唯一一个自定义的抽象方法,此接口就可以默认称作函数接口
实现方式:
- 在接口中定义唯一 一个自定义的抽象方法;
- 使用@FunctionInterface注解:目的是为了强制接口只有唯一一个抽象方法,可以存在static、default修饰的普通方法。
public static void main(String[] args) {
UserService userService=new UserService(){
@Override
public void insert(String name,Integer age){
System.out.println("name:"+name+"...........age:"+age);
}
};
userService.insert("命硬",22);
}
UserService userService1 = (name, age) -> {
System.out.println("name:" + name + "..............age" + age);
};
userService1.insert("命硬", 22);
使用Lambda简化匿名内部类
public static void main(String[] args) {
/**
* 使用匿名内部类实现线程
*
* @param
* @return void
* @time: 2020/1/16 16:28
*/
Runnable runnable=new Runnable(){
@Override
public void run() {
System.out.println("主线程名称:"+Thread.currentThread().getName());
}
};
new Thread(runnable).start();
/**
* 使用Lambda简化匿名内部类
*
* @param
* @return void
* @time: 2020/1/16 16:29
*/
new Thread(()->{
System.out.println("主线程名称:"+Thread.currentThread().getName());
});
}
遍历集合的三种方式:
ArrayList<String> list = new ArrayList<>();
list.add("小彪子");
list.add("小鹏子");
list.add("小康子");
/**
* 使用匿名内部类遍历集合
*
* @param
* @return void
* @time: 2020/1/16 16:47
*/
System.out.println("使用匿名内部类遍历集合");
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
/**
*
* 使用Lambda表达式遍历集合
*
* @param
* @return void
* @time: 2020/1/16 16:51
*/
System.out.println("使用Lambda遍历集合");
list.forEach((t) -> {
System.out.println(t);
});
/**
*
* 使用方法引用形式遍历集合
* @param
* @return void
* @time: 2020/1/16 16:53
*/
System.out.println("使用方法引用形式遍历集合");
list.forEach(System.out::println);
运行结果:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL0kFROpXR610dRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzMjN5QDOxcTM2ETMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
方法引入
静态方法引入
@FunctionalInterface
public interface FunctionInterfaceTest {
void test();
}
public class Test {
public static void main(String[] args) {
/** 静态方法引入 */
System.out.println("****静态方法引入***");
// FunctionInterfaceTest functionInterfaceTest1=()->Test.test();
FunctionInterfaceTest functionInterfaceTest2 = Test::test;
functionInterfaceTest2.test();
}
public static void test(){
System.out.println("静态方法引入");
}
}
注意:静态方法引入的静态方法需要和函数式接口的参数和返回类型一致。实例方法引入和静态方法遵循引入相同规则。
实例方法引入
@FunctionalInterface
public interface FunctionInterfaceTest {
String test();
}
public class Test {
public static void main(String[] args) {
System.out.println("****实例方法引入***");
Test test = new Test();
FunctionInterfaceTest functionInterfaceTest1=()->test.sing();
FunctionInterfaceTest functionInterfaceTest2 = test::sing;
System.out.println(functionInterfaceTest1.test());
System.out.println(functionInterfaceTest2.test());
}
public String sing(){
return "五月天唱了一首《突然好想你》!";
}
}
运行结果:
注意:若函数接口的参数和实例对象是一个对象则无需实例化对象。
@FunctionalInterface
public interface FunctionInterfaceTest {
String test(Test test);
}
public class Test {
public static void main(String[] args) {
// FunctionInterfaceTest functionInterfaceTest =(test)->test.sing();
FunctionInterfaceTest functionInterfaceTest =Test::sing;
}
public String sing(){
return "五月天唱了一首《突然好想你》!";
}
}
构造函数引入
@FunctionalInterface
public interface FunctionInterfaceTest {
Music test();
}
System.out.println("****构造函数引入***");
FunctionInterfaceTest functionInterfaceTest = Music::new;
System.out.println(functionInterfaceTest.test());
运行结果:
Lambda(简化匿名内部类)
使用Lambda表达式排序
List<Music> musicList = new ArrayList<>();
musicList.add(new Music("《好好》","阿信",20));
musicList.add(new Music("《晴天》","周杰伦",21));
musicList.add(new Music("《云烟成雨》","房东的猫",18));
musicList.sort((music1,music2)->music1.getAge()-music2.getAge());
musicList.forEach(o->System.out.println(o.toString()));
运行结果
Steam流
List<Music> musicList = new ArrayList<>();
musicList.add(new Music("《好好》","阿信",20));
musicList.add(new Music("《晴天》","周杰伦",21));
musicList.add(new Music("《云烟成雨》","房东的猫",18));
musicList.add(new Music("《云烟成雨》","房东的猫",20));
limit分页
/** limit分页 */
System.out.println("limit分页");
musicList.stream().skip(1).limit(3).forEach(music-> System.out.println(music));
运行结果
注意:skip为跳过元素
sorted 排序
/** sorted 排序 */
System.out.println("sorted 排序");
System.out.println("降序");
musicList.stream().sorted((music1,music2)->music2.getAge()-music1.getAge()).forEach(music -> System.out.println(music));
System.out.println("升序");
musicList.stream().sorted(Comparator.comparingInt(Music::getAge)).forEach(music -> System.out.println(music));
运行结果:
filter过滤
/** filter过滤*/
System.out.println("filter过滤");
musicList.stream().filter(music -> "《云烟成雨》".equals(music.getName()) && music.getAge() > 18)
.forEach(v -> System.out.println(v));
Match匹配
/** match 匹配 **/
System.out.println("anyMatch匹配");
/** 若任意元素满足条件即可*/
boolean a = musicList.stream().anyMatch(music -> "《好好》".equals(music.getName()));
System.out.println(a);
/** 若所有元素满足条件*/
boolean b = musicList.stream().allMatch(music -> "《好好》".equals(music.getName()));
System.out.println(b);
/** 所有元素都不满足条件*/
boolean c = musicList.stream().noneMatch(music -> "《好好》".equals(music.getName()));
System.out.println(c);
List中元素属性查找最大值和最小值
/** 使用stream流 查找list中的属性 最大值和最小值**/
// Optional<Music> max = musicList.stream().max((music1, music2) -> music1.getAge() - music2.getAge());
// System.out.println("最大值:"+max);
Optional<Music> max = musicList.stream().max(Comparator.comparingInt(Music::getAge));
System.out.println("最大值:"+max);
运行结果:
List中元素属性求和
Optional<Music> musicOptional = musicList.stream().reduce((music, music2) ->
new Music("sumAge", "ls", music.getAge() + music2.getAge())
);
System.out.println(musicOptional.get());
运行结果
List转Set
Set<Music> musicSet = musicList.stream().collect(Collectors.toSet());
musicSet.forEach(music -> {
System.out.println(music.toString());
});
运行结果
注意:这里Music类使用了@Data注解重写了equals方法。若转换成set集合后没有对元素去重,对象应该没有重写equals方法。
List转Map集合
Map<String, Music> musicMap = musicList.stream().collect(Collectors.toMap(Music::getName, Function.identity(),(music1,music2) -> music2));
musicMap.forEach((k,v)-> System.out.println(k+"------"+v.toString()));
运行结果
注:Function.identity等价于 t->t。也可写成Map<String, Music> musicMap = musicList.stream().collect(Collectors.toMap(Music::getName, music -> music)),但是若该musicList集合中key有相同的值,则会抛异常java.lang.IllegalStateException: Duplicate key Music(name=《云烟成雨》, author=房东的猫, age=18),请不要使用该方式,应该指明若存在相同key的情况下是否替换旧值。
Java 8允许在接口中加入具体方法。接口中的具体方法有两种,default方法和static方法,identity()就是Function接口的一个静态方法。
Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如
形式的Lambda表达式。
t -> t
List转Map并指定分组属性
代码
public class StreamDemo {
public static void main(String[] args) {
List<Music> list = new ArrayList<>();
list.add(new Music("好好", "五月天"));
list.add(new Music("理想", "赵雷"));
list.add(new Music("突然好想你", "五月天"));
Map<String, List<Music>> map = list.stream().collect(Collectors.groupingBy(Music::getAuthor));
map.forEach((k, v) -> {
System.out.println(k + ":" + v.toString());
});
}
}
运行结果
List去重
代码(若作者相同,则删除后面的对象)
List<Music> arrayList = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Music::getAuthor))), ArrayList::new));
arrayList.forEach(System.out::println);
运行结果
Optional
public class OptionalTest {
public static void main(String[] args) {
Music music = new Music();
music.setName("五月天");
String name = music.getName();
Optional<String> nameOptional = Optional.ofNullable(name);
/** 判断是否为空 isPresent() 如果是false,则对象为null;如果为true,对象不为null */
// boolean present = nameOptional.isPresent();
// System.out.println(nameOptional.get());
// System.out.println(present);
/** 如果为null,设置默认值 */
// String newName = Optional.ofNullable(name).orElse("含老八");
// System.out.println(newName);
/** filter过滤 */
boolean present = Optional.ofNullable(name).filter(s -> "五月天".equals(name)).isPresent();
System.out.println(present);
/** 直接判断是否有值 */
Optional.ofNullable(name).ifPresent(System.out::println);
}
}