从JDK1.8开始为了简化使用者进行代码的开发,专门提供有Lambda表达式的支持,利用此操作可以实现函数式的编程,对于函数式编程比较著名的语言有:Haskell、Scala,利用函数式的编程可以避免掉面向对象编程之中一些繁琐的处理问题。
代码范例
public class Demo {
public static void main(String[] args) {
PrintString ps = new PrintString() {
@Override
public void print(String str) {
System.out.println(str);
}
};
ps.print("Lambda");
}
}
interface PrintString{
void print(String str);
}
在这样的程序里,实际上核心的功能只有一行语句System.out.println(str),但是为了这一行的核心语句,我们仍然需要按照完整的面向对象给出的结构进行开发。于是这些问题随着技术的发展也是越来越突出了。
使用Lambda表达式后的代码
public class Demo {
public static void main(String[] args) {
PrintString ps = str -> System.out.println(str);
ps.print("Lambda");
}
}
interface PrintString{
void print(String str);
}
如果要创建接口的实现类,且该类只是使用一次,那么可以使用匿名内部类,但是匿名内部类写起来很麻烦。而当接口中只有一个抽象方法时,该接口就是一个函数式接口,那么我们就可以使用 Lambda 来代替匿名内部类。Lambda 体就是接口的实现。
public class Demo_a {
public static void main(String[] args) {
PrintString ps = () -> System.out.println("Lambda");
ps.print();
}
}
interface PrintString{
void print();
}
注意:
抽象方法如果没有参数,则 lambda 表达式不能省略 ();
public class Demo {
public static void main(String[] args) {
Addition addition = new Addition() {
@Override
public int add(Integer i1, Integer i2) {
return i1 + i2;
}
};
System.out.println(addition.add(1,2));
}
}
interface Addition{
int add(Integer i1, Integer i2);
}
---------简化后------------
public class Demo {
public static void main(String[] args) {
Addition addition = (Integer i1, Integer i2) -> i1 + i2;
System.out.println(addition.add(1,2));
}
}
interface Addition{
int add(Integer i1, Integer i2);
}
Lambda 的本质就是函数式接口的一个实现类。
public class Demo {
public static void main(String[] args) {
// 获得 Stream 对象
int[] arr = {1,2,3,4};
// 1.List 获得stream对象
List<String> list = List.of("张三", "李四", "哈尔吉亚斯");
Stream<String> stream1 = list.stream();
// 2.Set获得 stream对象
Set<String> set = Set.of("牛肉馅包子", "鸡肉馅饺子", "猪肉陷阱");
Stream<String> stream2 = set.stream();
// 3.Map获得Stream对象
Map<String, Integer> map = Map.of("杯子", 23, "勺子", 2, "本子", 5,"奶茶",30);
Stream<String> stream3 = map.keySet().stream();
Stream<Integer> stream4 = map.values().stream();
Stream<Map.Entry<String, Integer>> stream5 = map.entrySet().stream();
// 4.数组获得Stream对象
String[] strArr = {"联想", "华硕", "惠普", "华为"};
Stream<String> stream6 = Arrays.stream(strArr);
// 5.直接将很多元素包装成Stream
Stream<Integer> stream7 = Stream.of(18, 20, 31, 12, 10);
System.out.println(stream1);
}
}
Stream
接口自身类型的方法,因此支持链式调用。(除了终结方法Stream
接口自身类型的方法,因此不再支持类似 StringBuilder
那虽然方法名字叫 forEach
,但是与for循环中的“for-each”昵称不同。
void forEach(Consumer<? super T> action); 1
该方法接收⼀个 Consumer
接口函数,会将每一个流元素交给该函数进行处理。
public class Demo {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张⽆忌", "张三丰", "周芷若");
stream.forEach(name-> System.out.println(name));
}
}
可以通过 filter
方法将⼀个流转换成另一个子集流。
Stream<T> filter(Predicate<? super T> predicate);
该接口接收⼀个 Predicate
函数式接口参数(可以是⼀个Lambda或方法引用)作为筛选条件。
示例代码
public class Demo {
public static void main(String[] args) {
Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
Stream<String> result = original.filter(s -> s.startsWith("张"));
}
}
如果需要将流中的元素映射到另⼀个流中,可以使用 map
方法。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
该接口需要⼀个 Function
函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
示例代码
public class Demo {
public static void main(String[] args) {
Stream<String> original = Stream.of("10", "12", "18");
Stream<Integer> result = original.map(str->Integer.parseInt(str));
}
}
正如旧集合 Collection 当中的 size
方法⼀样,流提供 count 方法来数⼀数其中的元素个数
long count();
该方法返回⼀个long值代表元素个数(不再像旧集合那样是int值)。
示例代码
public class Demo {
public static void main(String[] args) {
Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
Stream<String> result = original.filter(s -> s.startsWith("张"));
System.out.println(result.count()); // 2
}
}
limit
方法可以对流进行截取,只取用前n个。
Stream<T> limit(long maxSize);
参数是⼀个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
示例代码
public class Demo {
public static void main(String[] args) {
Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
Stream<String> result = original.limit(2);
System.out.println(result.count()); // 2
}
}
如果希望跳过前几个元素,可以使用 skip
方法获取⼀个截取之后的新流:
Stream<T> skip(long n);
如果流的当前长度大于n,则跳过前n个;否则将会得到⼀个长度为0的空流。
示例代码
public class Demo {
public static void main(String[] args) {
Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
Stream<String> result = original.skip(2);
System.out.println(result.count()); // 1
}
}
如果有两个流,希望合并成为⼀个流,那么可以使⽤ Stream
接口的静态方法 concat
:
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
示例代码
public class Demo {
public static void main(String[] args) {
Stream<String> streamA = Stream.of("张⽆忌");
Stream<String> streamB = Stream.of("张翠⼭");
Stream<String> result = Stream.concat(streamA, streamB);
}
}