一.常用的特性
二.Lambda表达式
是带有参数变量的表达式,是可以传递的,可以被一次或多次执行。
是一种精简的字面写法,其实就是把匿名内部类中“一定”要做的工作省略掉,然后由JVM通过推导把简化的表达式还原
格式: (parameters参数) -> expression表达式或方法体
paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数
->:可理解为“被用于”的意思
方法体:可以是表达式也可以代码块,是函数式接口里方法的实现
如果负责运算的代码无法用表达式表示,可以使用编写方法实现,但必须用{}包围并按需明确使用 return语句。
1. 需求:对字符串数组按字符串长度排序
public class Demo{
public static void main(String[] args) {
// 定义字符串数组
String[] strArr = { "abc", "cd", "abce", "a" };
// 传统方法
// 匿名内部类
Arrays.sort(strArr, new Comparator() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s2.length(), s1.length());
}
});
// 输出排序结果
for (String s : strArr) {
System.out.println(s);
}
System.out.println("---------------------");
// Lambda表达式
Arrays.sort(strArr, (s1, s2) -> Integer.compare(s2.length(), s1.length()));
// 输出
for (String s : strArr) {
System.out.println(s);
}
2. 需求:用Lambda实现多线程
public class Demo{
public static void main(String[] args) {
// Lambda表达式
new Thread(() -> System.out.println(1 + "hello world")).start();
System.out.println("----------------");
// 方法体
new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(2 + "hello world");
}
}).start();
}
}
3.方法引用中::后只是方法名,不能加();
forEach()也是jdk8的新特性
比如:list.forEach((s) -> System.out.println(s));---list.forEach(Syetem.out::println);
4.stream概述
是用函数式编程方式在集合类上进行复杂操作的工具,更像一个高级版本的 Iterator
原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作
高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作
Stream 会隐式地在内部进行遍历,做出相应的数据转换
而和迭代器又不同的是,Stream 可以并行化操作
借助于 Lambda 表达式,极大的提高编程效率和程序可读性
常用操作:
迭代集合中元素。接收一个 Lambda 表达式
然后在 Stream 的每一个元素上执行该表达式
此操作是及早求值方法
由Stream 里的值生成一个列表,是一个及早求值操作
很多Stream 操作都是惰性求值,因此调用Stream 一系列方法之后
还需最后再调用一个类似collect 的及早求值方法返回集合
开篇的例子:(再将符合要求的字符串放到一个新的集合里)
使用filter过滤器:遍历数据并检查其中的元素
public class Demo{
public static void main(String[] args) {
// 创建集合
List list = new ArrayList<>();
// 添加元素
list.add("sdf");
list.add("a");
list.add("asdf");
list.add("d");
list.add("basdfgh");
// 统计长度大于2的
long count = list.stream().filter((s) -> s.length() > 2).count();
// 将符合要求的放入集合
List list2 = list.stream().filter((s) -> s.length() > 2).collect(Collectors.toList());
System.out.println(count);
list2.forEach(System.out :: println);
}
}
如果有一个函数可以将一种类型的值转换成另外一种类型
map 操作就可以使用该函数,将一个流中的值转换成一个新的流
需求:将字符串全转换成大写
public class Demo{
public static void main(String[] args) {
// 创建集合
List list = new ArrayList<>();
// 添加元素
list.add("sdf");
list.add("a");
list.add("asdf");
list.add("d");
list.add("basdfgh");
// 转换为大写
List list2 = list.stream().map((s) -> s.toUpperCase()).collect(Collectors.toList());
list2.forEach(System.out :: println);
}
}
遍历数据并检查其中的元素。例如获取字符串List中以数字开始的字符集合
public class Demo{
public static void main(String[] args) {
// 创建集合
List
// 添加元素
list.add("1sdf");
list.add("a");
list.add("2asdf");
list.add("d");
list.add("basdfgh");
// 获取数字开头的
List
list2.forEach(System.out::println);
}}
可用Stream 替换值, 然后将多个Stream 连接成一个Stream
map 操作可用一个新的值代替Stream 中的值
若用户希望让map操作有点变化
生成一个新的Stream 对象取而代之则flatMap适用
假设有一个包含多个列表的流,现在希望得到所有数字的序列
public class Demo{
public static void main(String[] args) {
Stream> flatMap = Stream.of(Arrays.asList("a", "b"), Arrays.asList(1, 2, 3)).flatMap((s) -> s.stream());
flatMap.forEach(System.out :: println);
}
获取Stream中最大值或最小值,获取字符串List中长度最长的字符串长度
public class Demo01 {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("abc");
list.add("ab");
list.add("abcd");
list.add("abcde");
// 获取最大值
int max = list.stream().map((s) -> s.length()).max(Integer :: compareTo).get();
System.out.println(max);
// 获取最小值,另一种方法
int min = list.stream().min(Comparator.comparing((s) -> s.length())).get().length();
System.out.println(min);
}