Lambda表达式
1. Lanbda表达式标准格式
//Lambda表达式的标准格式为:(参数类型 参数名称) -> { 代码语句 }
格式说明:
小括号内的语法与传统方法参数列表一致:
无参数则留空;多个参数则用逗号分隔。
2. Lanbda表达式省略格式
1. 小括号内参数的类型可以省略;
2. 如果小括号内有且仅有一个参,则小括号可以省略;
3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号
3. Lanbda表达式的前提条件
Lambda的语法非常简洁,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:
1. 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的Runnable 、 Comparator 接口还是自定义的接口,
只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
2. 使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才 能使用Lambda作为该接口的实例
Stream流
Stream流获取方式
1. 所有的 Collection 集合都可以通过 stream 默认方法获取流;default Stream<E> stream() 返回一 个序列 Stream与此集合作为其来源【通过Collection接口的子类对象调用stream()方法获得Stream象】
2. Stream 接口的静态方法 of 可以获取数组对应的流。
static <T> Stream<T> of(T t) 返回包含单个元素的序列 Stream 。
static <T> Stream<T> of(T... values) 返回其元素是指定值的顺序排序流。
Stream流创建方式
// ArrayList获取流
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
// 根据Map获取流,java.util.Map
//map key
HashMap<String ,String> map = new HashMap<>();
Stream<String> stream = map.keySet().stream();
//map 对整个map进行遍历
Stream<Map.Entry<String, String>> stream1 = map.entrySet().stream();
//map value
Stream<String> stream2 = map.values().stream();
Stream接口常用方法:
//终结方法:
终结方法包括 count 和 forEach 方法。
//非终结方法:
返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为非终结方法。)
方法名 方法作用 方法种类 是否支持链式调用
count 统计个数 终结 否
forEach 逐一处理 终结 否
filter 过滤 函数拼接 是
limit 取用前几个 函数拼接 是
skip 跳过前几个 函数拼接 是
map 映射 函数拼接 是
concat 组合 函数拼接 是
foreach
forEach : 逐一处理 (遍历循环)
// 该方法并不保证元素的逐一消费动作在流中是被有序执行的。
// 该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理。
void forEach(Consumer<? super T> action);
public class Demo04forEach {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> stream = Stream.of(names);
// 调用forEach方法,逐一处理 【s:遍历数组之后的单个元素对象,类似于上面增强for循环的s】
stream.forEach((name)->{
System.out.println(name);
});
}
}
//等同于
/**
for (String name : names) {
System.out.println(name);
}
*/
count
//count:统计个数
正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数:
long count();// 该方法返回一个long值代表元素个数(不再像旧集合那样是int值)。
public class Demo05count {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> stream = Stream.of(names);
// 统计个数
long count = stream.count();
System.out.println(count);
}
}
filter
//filter:过滤
可以通过 filter 方法将一个流转换成另一个子集流。方法声明:
// 该接口接收一个 Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。filter
Stream<T> filter(Predicate<? super T> predicate);
public class Demo06filter {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> stream = Stream.of(names);
// 过滤
long count = stream.filter(s -> s.startsWith("马")).count();
System.out.println(count);
}
}
/**
for (String s : names) {
s.startsWith("马");
}
*/
limit
//limit 对流进行截取,只取用前n个。
// 参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
Stream<T> limit(long maxSize);
public class Demo07limit {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> stream = Stream.of(names);
//foreach 逐一处理
stream.limit(2).forEach(s-> System.out.println(s));
}
}
skip
//skip:跳过前几个
如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流:
// 如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
Stream<T> skip(long n);
public class Demo08skip {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> stream = Stream.of(names);
stream.skip(2).forEach(s-> System.out.println(s));
}
}
map
//map就是把一个数据经过处理后通过map转到另一个流foreach遍历输出
//map:映射
如果需要将流中的元素映射到另一个流中,可以使用 map 方法。方法签名:
// 该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
// map 方法的参数通过方法引用,将字符串类型转换成为了int类型(并自动装箱为Integer 类对象)
例如:stream.map(s->Integer.parseInt(s));
public class Demo09map {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> stream = Stream.of(names);
stream.map(s->s.substring(1)).forEach(s-> System.out.println(s));
}
}
concat
//concat:组合 会输出两个流的结果
//现获取streamA 在获取streamB ,然后Stream(streamA,streamB) 输出
如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
注意:这是一个静态方法,与 java.lang.String 当中的 concat 方法是不同的。
public class Demo10concat {
public static void main(String[] args) {
// 创建一个数组
String[] namesA = {"马松","马驰骏","马驰骋","晋世豪"};
// 将数组整成一个Stream流
Stream<String> streamA = Stream.of(namesA);
// 创建一个数组
String[] namesB = {"王明明","王琳栋","王春晓","罗志祥"};
// 将数组整成一个Stream流
Stream<String> streamB = Stream.of(namesB);
// 拼接
Stream.concat(streamA,streamB).fo+rEach(s-> System.out.println(s));
}
}
collect 收集到集合中
//收集到集合中 collect就相当于foreach循环的 sout 打印
//collect可以吧所有元素收集到一个集合中
Stream流接口提供方法:
<R,A> R collect(Collector<? super T,A,R> collector) 使用 Collector对此流的元素执行 mutable reduction操作。
而 java.util.stream.Collectors 类提供一些方法,可以作为Collector 接口的实例
public static <T> Collector<T, ?, List<T>> toList() :转换为 List 集合。
public static <T> Collector<T, ?, Set<T>> toSet() :转换为 Set 集合。
public class Demo01StreamToCollection {
public static void main(String[] args) {
// 创建一个数组
String[] names = {"马松","马驰骏","马驰骋","晋世豪","马松"};
List<String> list = stream.filter(s -> s.startsWith("马")).collect(Collectors.toList());
for (String s : list) {
System.out.println(s);
}
}
}
collect收集到数组中
//收集到数组中
Stream提供 toArray 方法来将结果放到一个数组中,方法签名:
Object[] toArray() 返回一个包含此流的元素的数组。
// 定义集合
List<String> list = new ArrayList<>();
list.add("jack");
// 转成数组
Object[] array = list.stream().toArray();