1.Lamdba表达式
就相当于要使用接口Lock就不需要再创建一个类去实现接口了,直接用Lambda表达式省略了在创建的那个类。
Lamdba表达式是什么?
“->”,Lambda操作符或箭 头操作符,它将Lambda表达式分割为两部分。
左边:指Lambda表达式的所有参数
右边:指Lambda 体,即表示Lambda表达式需要执行的功能
public static void main(String[] args) {
//使用匿名函数
new Thread(new Runnable(){
@Override
public void run(){
System.out.println("我是没有使用Lambda表达式:不简洁");
}
}).start();
//使用Lambda表达式
new Thread(
()->System.out.println("我是使用Lambda表达式:简洁、灵活")
).start();
}
六种语法格式:
1. 语法格式一:无参数、无返回值,只需要一个Lambda体
//接口
public interface Lock {
public abstract void lockUp(String str);
}
//主方法使用接口
public static void main(String[] args) {
Lock lock = ()->
System.out.println("Lambda表达式:简洁、灵活,优雅永不过时");
lock.lockUp();
}
2. 语法格式二:lambda有一个参数、无返回值
public interface Lock {
public abstract void lockUp(String str);
}
//有一个参数,无返回值
Lock lock = (s) -> System.out.println(s+"上锁");
lock.lockUp("张三");
3. 语法格式三:Lambda只有一个参数时,可以省略()
Lock lock = s -> System.out.println(s+"上锁");
lock.lockUp("张三");
4. 语法格式四:Lambda有两个参数时,并且有返回值
//接口
public interface Lock {
public abstract String lockUp(String str,String str2);
}
// 有两个参数并且有返回值
Lock lock = (s1,s2) ->{
System.out.println("门被上锁");
return "上锁";
};
lock.lockUp("张三",2);
5.语法格式五:当Lambda体只有一条语句的时候,return和{}可以省略掉
现在连return和{}都不要了
Lock lock1 = (s1,s2) ->"拉屎";
lock1.lockUp("张三",2);
6.语法格式六:类型推断
//写上类型
Lock lock2 = (s)-> System.out.println(s+"上锁");
lock2.lockUp("张三");
//可以不写类型
Lock lock = (s)-> System.out.println(s+"上锁");
lock.lockUp("张三");
2. forEach+Lambda
1. 使用forEach和Lambda循环list集合
本来是应该这样子使用循环的
//使用forEach和Lambda循环list集合
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
for (String s:list){
System.out.println(s);
}
使用Lambda表达式的循环
//使用forEach和Lambda循环list集合
list.forEach(s->System.out.println(s));
Lambda版:
这里的s就代表add的括号里面的参数
List<UserVo> list = new ArrayList<UserVo>();
list.add(new UserVo());
list.add(new UserVo());
list.add(new UserVo());
list.forEach(s->System.out.println(s.getUserName()));
2. 使用forEach和Lambda循环Map集合
这里的k就代表第一个参数,v就代表第二个参数
Map<String, UserVo> map = new HashMap<String, UserVo>();
map.put("A", new UserVo());
map.put("B", new UserVo());
map.put("C", new UserVo());
map.forEach((k,v)->System.out.println(k+"==="+v.getUserName()));
3.函数式接口:
因为接口中可能会有很多方法,我们如果用Lambda是默认的接口中的那个方法,所以函数式接口就是只包含一个抽象方法的接口。使用@FunctionalInterface 注解。符合函数式接口的才能够使用表达式。
接口中有两个方法就会报错
4. 方法引用和构造器引用
4.1方法引用
因为接口如果想实现方法需要借别人的方法体,::后面的就是别人的方法,也就是你想用的方法
接着简化Lambda表达式
使用操作符“::”将方法名和(类或者对象)分割开来。
有下列三种情况:
对象::实例方法
类::实例方法
类::静态方法
对象::实例方法
Lock lock = System.out::println; 使用了方法引用,表示将 System.out 对象的 println 方法作为 lockUp 的实现。
当调用lock.lockUp(""); 时,它实际上调用的是 System.out.println(" ");。
@FunctionalInterface
public interface Lock {
public abstract void lockUp(String str); //上锁
}
Lock lock = System.out::println;
lock.lockUp("测试。。。");
例题:
像这一题使用的类::静态方法因为Runnable里面的run( )没有方法体,借用的Hello类里面的a方法,然后用调用run方法时就调用的是Hello里面的a方法了,因为有两个方法a
我们要选择适合自己的,第二个a有参数所以pass
4.2构造器引用
格式:ClassName :: new
代码分析:
- Lock 是一个函数式接口,定义了一个抽象方法 lockUp,其接受一个 String参数并返回一个 String。
- 当我们调用方法时需要返回一个String,所以Lambda省略了return和{}之后是这样的
- 所以根据构造器的格式就是String::new
@FunctionalInterface
public interface Lock {
public abstract String lockUp(String str); //上锁
}
//非构造器引用
Lock lock1 = (s) -> new String(s);
//构造器引用
Lock lock2 = String::new;
5. Stream API
Java8中两个最为重要特性:第一个的是Lambda表达式,另一个是Stream API。
StreamAPI帮助我们更好地对数据进行集合操作,它本质就是 对数据的操作进行流水线式处理,也可以理解为一个更加高级的迭代器,主要作用是遍其中每一个元 素。简而言之,StreamAP提供了一种高效且易于使用的处理数据方式。
Stream特点:
1、Stream自己不会存储数据。
2、Stream不会改变源对象。相反,它们会返回一个持有结果的新Stream对象
3、Stream操作时延迟执行的。这就意味着它们等到有结果时候才会执行。
3. Stream操作的三个步骤?
1、创建Stream:一个数据源(例如:set 、list),获取一个流
2、中间操作:一个中间操作连接,对数据源的数据进行处理
3、终止操作:一个终止操作,执行中间操作连,产生结果。
4. Stream创建可以通过三种方式创建。
1. 通过 java.util.Collection.stream() 方法用集合创建流
2. 使用 java.util.Arrays.stream(T[] array) 方法用数组创建流
3. 使用 Stream 的静态方法: of()、iterate()、generate()
//1.通过 `java.util.Collection.stream()` 方法用集合创建流
List<String> list = Arrays.asList("d","a", "b", "c");
Stream<String> streamList = list.stream();
System.out.println("###############顺序流##############");
streamList.forEach(System.out::print);
System.out.println();
System.out.println("###############并行流##############");
// 创建一个并行流
//效率高,线程不安全
Stream<String> parallelStream = list.parallelStream();
parallelStream.forEach(System.out::print);
System.out.println();
//2.使用`java.util.Arrays.stream(T[] array)`方法用数组创建流
int[] array={1,3,5,6,8};
IntStream streamint = Arrays.stream(array);
streamint.forEach(System.out::print);
System.out.println();
//3.使用`Stream`的静态方法:`of()、iterate()、generate()
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
stream.forEach(System.out::print);
System.out.println();
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::print);
System.out.println();
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::print);
System.out.println();
5.中间操作:
用这个代码举例子
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰","张无
忌");
}
(1).limit(n) 从list中取出n个元素
list.stream().limit(2).forEach(System.out::println);
(2).skip(n) 从list第n个元素开始,取出所有元素
list.stream().skip(3).forEach(System.out::println);
(3).distinct() 去除重复
list.stream().distinct().forEach(System.out::println);
(4).filter(Predicate<? super T> predicate) 筛选条件
括号中的内容为一个断言型函数式接口,其中的T为当前集合中元素的类型。
断言型函数式接口是指只包含一个抽象方法的接口,用于对输入进行测试并返回布尔值。
List<Person> userList = new ArrayList<>();
userList.add(new Person("欧阳雪", 18));
userList.add(new Person("Tom", 24));
userList.add(new Person("Harley", 22));
userList.add(new Person("向天笑", 20));
userList.add(new Person("李康", 22));
userList.add(new Person("小梅", 20));
userList.add(new Person("何雪", 21));
//打印对象要重写toString方法
userList.stream().filter((a) -> a.getAge() > 20)
.forEach(System.out::println);
(5).map(Function mapper ) 将元素转换成其他形式或提取信息。
// 将 Person 对象转换为其年龄
userList.stream().map(a -> a.getAge())
.forEach(System.out::println);
(6).sorted() 对元素进行排序
年龄由小到大, // 使用比较器比较年龄
userList.stream()
.sorted((a, b) -> Integer.compare(a.getAge(), b.getAge()))
.forEach(System.out::println); // 打印排序后的结果 }
终端操作:
1.forEach() 遍历流中每一个元素,会关闭流
list.stream().forEach(System.out::println);
2. findFirst(),findAny() 查找操作
查找第一个、任何一个,返回的类型为Optional可以用get方法获取字符串。
String first = list.stream().findFirst().get();
System.out.println(first);
3. allMatch,anyMatch,noneMatch
allMatch 要求Stream中所有元素都满足条件才返回true
anyMatch, 只要有1个元素满足就返回true
noneMatch 要求所有的元素都不满足条件才返回true
List<Person> userList = new ArrayList<>();
userList.add(new Person("欧阳雪", 18));
userList.add(new Person("Tom", 24));
userList.add(new Person("Harley", 22));
userList.add(new Person("向天笑", 20));
userList.add(new Person("李康", 22));
userList.add(new Person("小梅", 20));
userList.add(new Person("何雪", 21));
//每个学生年纪都为18才返回true
boolean flag = userList.stream().allMatch(e -> e.getAge() == 18);
//任意一个学生是18,则返回true
boolean flag1 = userList.stream().anyMatch(e -> e.getAge() == 18);
//学生年纪没有一个是18 ,则返回true
boolean flag2 = userList.stream().noneMatch(e -> e.getAge() == 18);
System.out.println("flag:"+flag+" flag1:"+flag1+" flag2:"+flag2);
4. reduce:将整个数据流的值规约为一个值
其中count、min、max底层就是使用reduce,也可用于 字符串连接
通过get返回
// 字符串连接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
// 集合累加求和,另一写法reduce(0,Integer::sum)
int sum2=Stream.of(1,2,3,4,5).reduce((t,u)->t+u).get();
//输出最大值,另一写法reduce(Integer::max)
int max1=Stream.of(1,2,3,4,5).reduce((t,u)-> t>=u? t:u).get();
5.min、max`最值操作:返回数据流中最大、最小的值
需要自定义比较器,
//查年纪最大的
Optional<Person> max =
userList.stream().max(Comparator.comparing(Person::getAge));
if (max.isPresent()) {
Person person = max.get();
System.out.println(person);
}
6. count : 返回Stream中元素的个数
long count = userList.stream().count();
System.out.println(count);
7. toArray 数组操作:将数据流的元素转换成数组
List<String> list=Arrays.asList("a","b","c","a");
//返回数组
String[] newArr=list.stream().toArray(String[]::new);
8.将Stream转换为list 语法:Stream对象名.collect(Collectors.toList());
List<Student> list = new ArrayList<Student>();
list.add(new Student("张三",18, "男"));
list.add(new Student("李四",17, "男"));
list.add(new Student("王五",19, "女"));
list.add(new Student("马化腾",37, "女"));
list.add(new Student("丁三石",19, "男"));
list.add(new Student("马浮云",31, "女"));
list.add(new Student("军儿",29, "男"));
//将Stream转换为list 语法:Stream对象名.collect(Collectors.toList());
List<Student> list1 = list.stream().
filter(t->t.getSage()>20).
collect(Collectors.toList());