1.lambda表达式
1.定义
Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),可以推导出来的就可以省略了,Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
2.例子
| |
| new Thread(() -> System.out.println("多线程任务执行!")).start(); |
3.标准格式
标准格式3个部分:
一些参数
一个箭头
一段代码
(参数类型 参数名称) ‐> { 代码语句 } 强调的是做什么而不是怎么做
| Runnable接口简化: |
| 1. () ‐> System.out.println("多线程任务执行!") |
| Comparator接口简化: |
| 2. Arrays.sort(array, (a, b) ‐> a.getAge() ‐ b.getAge()); |
4.前提条件
| 1.必须有接口,接口中有且仅有一个方法 |
| 2.必须有固定的格式,就是参数什么的固定的,可以推断出来 |
| 3. |
2.Stream流
1.什么是stream流
Stream流不同于InputStream和OutputStream.Jdk8中的Stream流是对集合(Collerction)的增强,增强了对集合对象的聚合操作,Stram API借助于Lambda表达式,他提供了串行和并行使用fork/join并行来拆分
2.常用
| 1.集合获取stream流的方式 |
| Stream<T> stream() |
| Stream<T> parallelStream() |
| 2. 数组获取stream流的方式 |
| Stream<T> Stream.of(T[]) |
| Stream<T> Arrays.stream(T[]); |
| 3. 文件获取stream流 |
| BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md")); |
| Stream<String> linesStream = bufferedReader.lines(); |
| 4.静态方法获取流操作 |
| IntStream rangeStream = IntStream.range(1, 10); |
| rangeStream.limit(10).forEach(num -> System.out.print(num+",")); |
| IntStream intStream = IntStream.of(1, 2, 3, 3, 4); |
| intStream.forEach(num -> System.out.print(num+",")); |
| Pipelining中间操作都会返回流对象本身,这样多个操作可以串联成一个管道 |
| |
| forEach() |
| map |
| filter |
| limit |
| public class StreamDemo1 { |
| public static void main(String[] args) throws FileNotFoundException { |
| demo1(); |
| } |
| public static void getStream() throws FileNotFoundException { |
| List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"); |
| String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"}; |
| |
| Stream<String> nameListStream = nameList.stream(); |
| |
| Stream<String> nameListStream2 = nameList.parallelStream(); |
| |
| Stream<String> nameArrStream = Stream.of(nameArr); |
| |
| Stream<String> nameArrStream1 = Arrays.stream(nameArr); |
| |
| BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md")); |
| Stream<String> linesStream = bufferedReader.lines(); |
| |
| |
| IntStream rangeStream = IntStream.range(1, 10); |
| rangeStream.limit(10).forEach(num -> System.out.print(num+",")); |
| IntStream intStream = IntStream.of(1, 2, 3, 3, 4); |
| intStream.forEach(num -> System.out.print(num+",")); |
| } |
| |
| |
| |
| |
| |
| |
| public static void demo1(){ |
| List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"); |
| nameList.stream() |
| .filter(name -> name.length() == 4) |
| .map(name -> "This is "+name) |
| .forEach(name -> System.out.println(name)); |
| } |
| |
| |
| |
| public static void demo2(){ |
| List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"); |
| List<String> collect = nameList.stream() |
| .map(String::toUpperCase) |
| .collect(Collectors.toList()); |
| collect.forEach(name-> System.out.println(name+",")); |
| } |
| |
| |
| |
| public void mapTest() { |
| List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); |
| |
| List<Integer> collect = numberList.stream() |
| .map(number -> number * 2) |
| .collect(Collectors.toList()); |
| collect.forEach(number -> System.out.print(number + ",")); |
| System.out.println(); |
| numberList.stream() |
| .map(number -> "数字 " + number + ",") |
| .forEach(number -> System.out.print(number)); |
| } |
| |
| |
| |
| public void flatMapTest() { |
| Stream<List<Integer>> inputStream = Stream.of( |
| Arrays.asList(1), |
| Arrays.asList(2, 3), |
| Arrays.asList(4, 5, 6) |
| ); |
| List<Integer> collect = inputStream |
| .flatMap((childList) -> childList.stream()) |
| .collect(Collectors.toList()); |
| collect.forEach(number -> System.out.print(number + ",")); |
| } |
| |
| |
| |
| |
| public void forEachTest(){ |
| List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); |
| numberList.stream().forEach(number -> System.out.print(number+",")); |
| } |
| |
| |
| |
| |
| |
| public void filterTest() { |
| List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); |
| List<Integer> collect = numberList.stream() |
| .filter(number -> number % 2 == 0) |
| .collect(Collectors.toList()); |
| collect.forEach(number -> System.out.print(number + ",")); |
| } |
| |
| |
| |
| |
| |
| public void findFirstTest(){ |
| List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); |
| Optional<Integer> firstNumber = numberList.stream() |
| .findFirst(); |
| System.out.println(firstNumber.orElse(-1)); |
| } |
| |
| |
| |
| |
| public void collectTest() { |
| List<Integer> numberList = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5); |
| |
| Integer[] toArray = numberList.stream() |
| .toArray(Integer[]::new); |
| |
| List<Integer> integerList = numberList.stream() |
| .collect(Collectors.toList()); |
| |
| Set<Integer> integerSet = numberList.stream() |
| .collect(Collectors.toSet()); |
| System.out.println(integerSet); |
| |
| String toString = numberList.stream() |
| .map(number -> String.valueOf(number)) |
| .collect(Collectors.joining()).toString(); |
| System.out.println(toString); |
| |
| String toStringbJoin = numberList.stream() |
| .map(number -> String.valueOf(number)) |
| .collect(Collectors.joining(",")).toString(); |
| System.out.println(toStringbJoin); |
| } |
| |
| |
| |
| |
| public void diffTest() { |
| |
| List<String> names = Arrays.asList("Jack", "Jill", "Nate", "Kara", "Kim", "Jullie", "Paul", "Peter"); |
| |
| List<String> subList = new ArrayList<>(); |
| for (String name : names) { |
| if (name.length() == 4) { |
| subList.add(name); |
| } |
| } |
| |
| StringBuilder sbNames = new StringBuilder(); |
| for (int i = 0; i < subList.size() - 1; i++) { |
| sbNames.append(subList.get(i)); |
| sbNames.append(", "); |
| } |
| |
| if (subList.size() > 1) { |
| sbNames.append(subList.get(subList.size() - 1)); |
| } |
| System.out.println(sbNames); |
| System.out.println("----------------"); |
| |
| |
| String nameString = names.stream() |
| .filter(num -> num.length() == 4) |
| .collect(Collectors.joining(", ")); |
| System.out.println(nameString); |
| |
| |
| String string = names.stream() |
| .filter(num -> num.length() == 4) |
| .map(name -> name.toUpperCase()) |
| .collect(Collectors.joining(",")); |
| } |
| |
| |
| |
| |
| public void reduceTest() { |
| List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python"); |
| String s = skills.stream().reduce((all, skill) -> all + skill).get(); |
| System.out.println(s); |
| } |
| |
| |
| |
| |
| public void distinctTest() { |
| List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python", "java"); |
| List<String> collects = skills.stream().distinct().collect(Collectors.toList()); |
| collects.forEach(skill -> System.out.println(skill)); |
| System.out.println("---------------------------------------------"); |
| skills = Arrays.asList("java", "golang", "c++", "c", "python", "java"); |
| skills.stream().distinct().forEach(s -> System.out.println(s)); |
| } |
| |
| |
| |
| |
| public void mathTest() { |
| List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); |
| IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics(); |
| System.out.println("最小值:" + stats.getMin()); |
| System.out.println("最大值:" + stats.getMax()); |
| System.out.println("个数:" + stats.getCount()); |
| System.out.println("和:" + stats.getSum()); |
| System.out.println("平均数:" + stats.getAverage()); |
| } |
| |
| |
| |
| |
| public void groupByTest() { |
| List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26); |
| Map<String, List<Integer>> ageGrouyByMap = ageList.stream() |
| .collect(Collectors.groupingBy(age -> String.valueOf(age / 10))); |
| |
| ageGrouyByMap.forEach((k, v) -> { |
| System.out.println("年龄" + k + "0多岁的有:" + v); |
| }); |
| } |
| |
| |
| |
| |
| |
| public void partitioningByTest() { |
| List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26); |
| Map<Boolean, List<Integer>> ageMap = ageList.stream() |
| .collect(Collectors.partitioningBy(age -> age > 18)); |
| System.out.println("未成年人:" + ageMap.get(false)); |
| System.out.println("成年人:" + ageMap.get(true)); |
| } |
| |
| |
| |
| |
| public void generateTest(){ |
| |
| Random random = new Random(); |
| Stream<Integer> generateRandom = Stream.generate(random::nextInt); |
| generateRandom.limit(5).forEach(System.out::println); |
| |
| |
| Stream<UUID> generate = Stream.generate(UUID::randomUUID); |
| generate.limit(5).forEach(System.out::println); |
| } |
| |
| |
| |
| |
| |
| public void limitOrSkipTest() { |
| |
| List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26); |
| ageList.stream() |
| .limit(3) |
| .forEach(age -> System.out.print(age+",")); |
| System.out.println(); |
| |
| ageList.stream() |
| .skip(3) |
| .forEach(age -> System.out.print(age+",")); |
| } |
| |
| |
| |
| |
| public void lazyTest() { |
| |
| List<Integer> numberLIst = Arrays.asList(1, 2, 3, 4, 5, 6); |
| |
| Stream<Integer> integerStream = numberLIst.stream() |
| .filter(number -> { |
| int temp = number % 2; |
| if (temp == 0 ){ |
| System.out.println(number); |
| } |
| return temp == 0; |
| }); |
| |
| System.out.println("分割线"); |
| List<Integer> collect = integerStream.collect(Collectors.toList()); |
| } |
| |
| |
| |
| |
| public void main() { |
| |
| Random random = new Random(); |
| Stream<Integer> generateRandom = Stream.generate(random::nextInt); |
| List<Integer> numberList = generateRandom.limit(10000000).collect(Collectors.toList()); |
| |
| |
| long start = System.currentTimeMillis(); |
| int sum = numberList.stream().map(number -> number * 2).mapToInt(x -> x).sum(); |
| long end = System.currentTimeMillis(); |
| System.out.println("串行耗时:"+(end - start)+"ms,和是:"+sum); |
| |
| |
| start = System.currentTimeMillis(); |
| sum = numberList.parallelStream().map(number -> number * 2).mapToInt(x -> x).sum(); |
| end = System.currentTimeMillis(); |
| System.out.println("并行耗时:"+(end - start)+"ms,和是:"+sum); |
| |
| } |
| |
| public void simpleTest(){ |
| List<Integer> numbers = Arrays.asList(1, 2, 3); |
| int[] factor = new int[] { 2 }; |
| Stream<Integer> stream = numbers.stream() |
| .map(e -> e * factor[0]); |
| factor[0] = 0; |
| stream.forEach(System.out::println); |
| } |
| |
| |
| } |
| |
3.函数式接口
1.定义
函数式接口就是有且仅有一个抽象方法的接口,java中的函数式编程就是Lambda,函数式接口可以使用于lambda表达式中,
2.格式
| 修饰符 interface 接口名称 { |
| public abstract 返回值类型 方法名称(可选参数信息); |
| |
| |
| } |
3.例子
| public interface MyFunctionalInterface { |
| void myMethod(); |
| } |
| public class FunctionalInterface { |
| |
| private static void doSomething(MyFunctionalInterface inter) { |
| inter.myMethod(); |
| } |
| public static void main(String[] args) { |
| |
| doSomething(()-> System.out.println("Lambda执行啦!")); |
| } |
| } |
4.自定义
| 与@Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface。该注解可用于一个接口的定义上 |
| 如果不使用这个注解,如果仍然满足要求,一样可以用,但是加上就必须满足,不然会报错 |
5.常用 java.util.function
1.Supplier接口
java.util.function.Supplier 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据
| @FunctionalInterface |
| public interface Supplier<T> { |
| T get(); |
| } |
| 调用这个方法就要返回一个T类型的数据,至于这个数据是如何加工出来的,可以自定义,所以是生产者 |
| |
例子
| public interface MyFunctionalInterface { |
| void myMethod(); |
| } |
| |
| public class FunctionalInterface { |
| |
| private static void doSomething(MyFunctionalInterface inter) { |
| inter.myMethod(); |
| } |
| public static void main(String[] args) { |
| |
| doSomething(()-> System.out.println("Lambda执行啦!")); |
| } |
| } |
| |
2.Consumer接口
java.util.function.Consumer 接口则正好相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛
型参数决定。
| @FunctionalInterface |
| public interface Consumer<T> { |
| |
| void accept(T t); |
| |
| |
| default Consumer<T> andThen(Consumer<? super T> after) { |
| Objects.requireNonNull(after); |
| return (T t) -> { accept(t); after.accept(t); }; |
| } |
| } |
| |
例子
| public class ConsumerDemo { |
| private static void consumeString(Consumer<String> one,Consumer<String> two) { |
| one.andThen(two).accept("hello"); |
| one.accept("ddd"); |
| } |
| |
| public static void main(String[] args) { |
| consumeString(s-> System.out.println(s.toUpperCase()),s-> System.out.println(s.toLowerCase())); |
| } |
| } |
| |
3.Predicate接口
java.util.function.Predicate 有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。
| @FunctionalInterface |
| public interface Predicate<T> { |
| |
| boolean test(T t); |
| |
| |
| default Predicate<T> and(Predicate<? super T> other) { |
| Objects.requireNonNull(other); |
| return (t) -> test(t) && other.test(t); |
| } |
| |
| |
| default Predicate<T> negate() { |
| return (t) -> !test(t); |
| } |
| |
| |
| default Predicate<T> or(Predicate<? super T> other) { |
| Objects.requireNonNull(other); |
| return (t) -> test(t) || other.test(t); |
| } |
| |
| |
| static <T> Predicate<T> isEqual(Object targetRef) { |
| return (null == targetRef) |
| ? Objects::isNull |
| : object -> targetRef.equals(object); |
| } |
| } |
| |
| public class PredicateAndTest { |
| public static void main(String[] args) { |
| |
| |
| methodNegate(s-> "Helloworld".equals(s),"Helloworld"); |
| } |
| private static void methodAnd(Predicate<String> one,Predicate<String> two,String str) { |
| boolean test = one.and(two).test(str); |
| System.out.println("字符串符合要求吗:" + test); |
| } |
| private static void methodOr(Predicate<String> one,Predicate<String> two,String str){ |
| boolean test = one.or(two).test(str); |
| System.out.println("字符串符合要求吗or:" + test); |
| } |
| private static void methodNegate(Predicate<String> one,String str){ |
| boolean test = one.negate().test(str); |
| System.out.println("字符串取反:" + test); |
| } |
| } |
| |
| |
4.Function<T,R> 接口
简单的说就是类型转换,就是一种类型的数据转换成为另外一个类型的数据,把T类型的转换成R类型的,有进有出
| @FunctionalInterface |
| public interface Function<T, R> { |
| |
| R apply(T t); |
| |
| |
| default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { |
| Objects.requireNonNull(before); |
| return (V v) -> apply(before.apply(v)); |
| } |
| |
| default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { |
| Objects.requireNonNull(after); |
| return (T t) -> after.apply(apply(t)); |
| } |
| |
| |
| static <T> Function<T, T> identity() { |
| return t -> t; |
| } |
| } |
| |
| |
例子
| public class FunctionDemo { |
| public static void main(String[] args) { |
| method(s -> Integer.parseInt(s),"10"); |
| method2(new Function<String, Integer>() { |
| @Override |
| public Integer apply(String s) { |
| return 1; |
| } |
| }); |
| methodAddthen(s -> Integer.parseInt(s),s->s+10,"1"); |
| } |
| |
| private static void method(Function<String, Integer> function, String str) { |
| int num = function.apply(str); |
| System.out.println(num + 20); |
| } |
| private static void method2(Function<String, Integer> function) { |
| int num = function.apply("33"); |
| System.out.println(num + 20); |
| } |
| private static void methodAddthen(Function<String, Integer> one,Function<Integer, Integer> two,String str) { |
| Integer apply1 = one.andThen(two).apply(str); |
| System.out.println(apply1 + 20); |
| } |
| } |
| |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构