JavaSE23-函数式接口&Stream流
1.函数式接口1.1 函数式接口概述概念有且仅有一个抽象方法的接口如何检测一个接口是不是函数式接口@FunctionalInterface放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败注意事项我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解。1.2 函数式接口作为方法的参数1 public class RunnableDemo { 2 public static void main(String[] args) { 3 startRunnable(() -> { 4 System.out.println(Thread.currentThread().getName() "启动了"); 5 }); 6 } 7 8 private static void startRunnable(Runnable r) { 9 new Thread(r).start();10 }11 }在Runnable中有如下定义1 @FunctionalInterface 2 public interface Runnable { 3 /** 4 * When an object implementing interface {@code Runnable} is used 5 * to create a thread, starting the thread causes the object's 6 * {@code run} method to be called in that separately executing 7 * thread. 8 * <p> 9 * The general contract of the method {@code run} is that it may10 * take any action whatsoever.11 *12 * @see java.lang.Thread#run()13 */14 public abstract void run();15 }1.3 函数式接口作为方法的返回值1 import java.sql.Connection; 2 import java.util.ArrayList; 3 import java.util.Collection; 4 import java.util.Collections; 5 import java.util.Comparator; 6 7 public class getComparetorDemo { 8 public static void main(String[] args) { 9 ArrayList<String> list = new ArrayList<>();10 list.add("aaa");11 list.add("b");12 list.add("dd");13 list.add("cccc");14 15 System.out.println("排序前:" list);16 17 Collections.sort(list,getComparetor());18 19 System.out.println("排序后:" list);20 }21 22 private static Comparator<String> getComparetor() {23 return (s1,s2) -> s1.length() - s2.length();24 }25 }1.4 常用函数式接口之SupplierSupplier接口Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。构造方法方法名说明T get()按照某种实现逻辑(由Lambda表达式实现)返回一个数据返回字符串1 import java.util.function.Supplier; 2 3 public class SupplierDemo { 4 public static void main(String[] args) { 5 System.out.println(useSup( 6 () -> "hello world" 7 )); 8 } 9 10 private static String useSup(Supplier<String> sup) {11 return sup.get();12 }13 }返回最大值1 import java.util.function.Supplier; 2 3 public class SupplierDemo2 { 4 public static void main(String[] args) { 5 int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 21, 142, 11, 2241, 24}; 6 int maxValue = useSup(() -> { 7 int max = arr[0]; 8 9 for (int i = 0; i < arr.length; i ) {10 if (max < arr[i]) {11 max = arr[i];12 }13 }14 15 return max;16 });17 18 System.out.println(maxValue);19 }20 21 private static Integer useSup(Supplier<Integer> sup) {22 return sup.get();23 }24 } 1.5 常用函数式接口之ConsumerConsumer接口Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定常用方法方法名说明void accept(T t)对给定的参数执行此操作default Consumer andThen(Consumer after)返回一个组合的Consumer,依次执行此操作,然后执行after操作1 import java.util.function.Consumer; 2 3 public class ConsumerDemo { 4 public static void main(String[] args) { 5 String[] list = {"1,绿巨人","2,钢铁侠","3,美国队长"}; 6 7 printinfo(list,str -> System.out.print("序号" str.split(",")[0]),str -> System.out.println(str.split(",")[1])); 8 } 9 10 public static void printinfo(String[] list, Consumer<String> con1,Consumer<String> con2){11 for (String s : list){12 con1.andThen(con2).accept(s);13 }14 }15 }1.6 常用函数式接口之PredicatePredicate接口Predicate接口通常用于判断参数是否满足指定的条件方法名说明boolean test(T t)对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回 一个布尔值default Predicate negate()返回一个逻辑的否定,对应逻辑非default Predicate and(Predicate other)返回一个组合判断,对应短路与default Predicate or(Predicate other)返回一个组合判断,对应短路或1 import java.util.function.Predicate; 2 3 public class PredicateDemo { 4 public static void main(String[] args) { 5 boolean a = check("hello world",s -> s.length()<5); 6 System.out.println(a); 7 8 boolean b = uncheck("hello world",s -> s.length()<5); 9 System.out.println(b);10 }11 12 private static boolean check(String s , Predicate<String> pre){13 return pre.test(s);14 }15 16 private static boolean uncheck(String s , Predicate<String> pre){17 return pre.negate().test(s);18 }19 } 1.7 常用函数式接口之FunctionFunction接口Function<t,r>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值方法名说明R apply(T t)将此函数应用于给定的参数default Function andThen(Function after)返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果1 import java.util.function.Function; 2 3 public class FunctionDemo { 4 public static void main(String[] args) { 5 parseint("13729",s -> Integer.parseInt(s)); 6 } 7 8 private static void parseint(String s, Function<String,Integer> fun) { 9 int i = fun.apply(s);10 System.out.println(i);11 }12 }2.Strem流2.1 体验Stream流1 import java.util.ArrayList; 2 3 public class FilterDemo { 4 public static void main(String[] args) {//将姓张且名字在两个字(不含两个)以上的名字加入另一个集合 5 ArrayList<String> names = new ArrayList<>(); 6 7 names.add("张无忌"); 8 names.add("赵敏"); 9 names.add("张三丰");10 names.add("张果老");11 names.add("张国立");12 names.add("铁拐李");13 names.add("张赫");14 names.add("张飞");15 names.add("张翼德");16 names.add("刘备");17 names.add("关云长");18 names.add("曹孟德");19 names.add("吕轻侯");20 21 ArrayList<String> zhanglist = new ArrayList<>();22 23 names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() >=3).forEach(System.out::println);24 }25 }Stream流的好处直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印Stream流把真正的函数式编程风格引入到Java中2.2 Stream流的常见生成方式生成Stream流的方式Collection体系集合使用默认方法stream()生成流, default Stream stream()Map体系集合把Map转成Set集合,间接的生成流数组通过Stream接口的静态方法of(T... values)生成流1 import java.util.*; 2 import java.util.stream.Stream; 3 4 public class CreateStream { 5 public static void main(String[] args) { 6 //Collection体系直接使用stream() 7 List<String> list = new ArrayList<>(); 8 Stream<String> listStream = list.stream(); 9 10 Set<String> set = new TreeSet<>();11 Stream<String> setStream = set.stream();12 //Map体系间接生成13 Map<String,Integer> map = new HashMap<>();14 Stream<String> keyStream = map.keySet().stream();15 Stream<Integer> valueStream = map.values().stream();16 17 Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();18 //数组使用Stream接口的of()19 String[] nums = {"1","2","3","4"};20 Stream<String> numStringStream = Stream.of(nums);21 Stream<Integer> numStram = Stream.of(1,2,3,4,5);22 }23 }2.3 Stream流中间操作方法概念中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。常用方法方法名说明Stream filter(Predicate predicate)用于对流中的数据进行过滤Stream limit(long maxSize)返回此流中的元素组成的流,截取前指定参数个数的数据Stream skip(long n)跳过指定参数个数的数据,返回由该流的剩余元素组成的流static Stream concat(Stream a, Stream b)合并a和b两个流为一个流Stream distinct()返回由该流的不同元素(根据Object.equals(Object) )组成的流Stream sorted()返回由此流的元素组成的流,根据自然顺序排序Stream sorted(Comparator comparator)返回由该流的元素组成的流,根据提供的Comparator进行排序Stream map(Function mapper)返回由给定函数应用于此流的元素的结果组成的流IntStream mapToInt(ToIntFunction mapper)返回一个IntStream其中包含将给定函数应用于此流的元素的结果limit&skip1 import java.util.ArrayList; 2 3 public class limitandskipDemo { 4 public static void main(String[] args) { 5 ArrayList<String> names = new ArrayList<>(); 6 7 names.add("张无忌"); 8 names.add("赵敏"); 9 names.add("张三丰");10 names.add("张果老");11 names.add("张国立");12 names.add("铁拐李");13 names.add("张赫");14 names.add("张飞");15 names.add("张翼德");16 names.add("刘备");17 names.add("关云长");18 names.add("曹孟德");19 names.add("吕轻侯");20 21 //输出前三个22 names.stream().limit(3).forEach(System.out::println);23 System.out.println("-------");24 //跳过三个然后输出25 names.stream().skip(3).forEach(System.out::println);26 System.out.println("-------");27 //跳过四个输出五个28 names.stream().skip(4).limit(5).forEach(System.out::println);29 }30 }concat&distinct1 import java.util.ArrayList; 2 import java.util.stream.Stream; 3 4 public class concatanddistinctDemo { 5 public static void main(String[] args) { 6 ArrayList<String> names = new ArrayList<>(); 7 names.add("张无忌"); 8 names.add("赵敏"); 9 names.add("张三丰");10 names.add("张果老");11 names.add("张国立");12 names.add("铁拐李");13 14 //截取前四个为流s115 Stream<String> s1 = names.stream().limit(4);16 //跳过前两个为流s217 Stream<String> s2 = names.stream().skip(2);18 //合并s1,s219 // Stream.concat(s1, s2).forEach(System.out::println);20 //合并并去重21 Stream.concat(s1, s2).distinct().forEach(System.out::println);22 }23 }sort1 import java.util.ArrayList; 2 3 public class sortDemo { 4 public static void main(String[] args) { 5 ArrayList<String> names = new ArrayList<>(); 6 names.add("张无忌"); 7 names.add("赵敏"); 8 names.add("张三丰"); 9 names.add("张果老");10 names.add("张国立");11 names.add("铁拐李");12 13 names.stream().sorted((s1,s2) -> {14 int num = s1.length()-s2.length();15 int num2 = num == 0 ? s2.compareTo(s1) : num;16 return num2;17 }).forEach(System.out::println);18 }19 }maptoInt1 import java.util.ArrayList; 2 3 public class maptointDemo { 4 public static void main(String[] args) { 5 ArrayList<String> nums = new ArrayList<>(); 6 nums.add("1"); 7 nums.add("10"); 8 nums.add("100"); 9 nums.add("1000");10 nums.add("10000");11 nums.add("100000");12 13 int result = nums.stream().mapToInt(Integer::parseInt).sum();14 System.out.println(result);15 }16 }count1 import java.util.ArrayList; 2 3 public class countDemo { 4 public static void main(String[] args) { 5 ArrayList<String> names = new ArrayList<>(); 6 7 names.add("张无忌"); 8 names.add("赵敏"); 9 names.add("张三丰");10 names.add("张果老");11 names.add("张国立");12 names.add("铁拐李");13 names.add("张赫");14 names.add("张飞");15 names.add("张翼德");16 names.add("刘备");17 names.add("关云长");18 names.add("曹孟德");19 names.add("吕轻侯");20 21 long count = names.stream().filter(s -> s.startsWith("张")).count();22 System.out.println(count);23 }24 }练习这里有两个集合,有6个男演员和6个女演员,要求:男演员只要名字为3个字的前三人女演员只要姓林的,并且不要第一个把过滤后的男演员姓名和女演员姓名合并到一起把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据Actor类1 public class Actor { 2 private String name; 3 4 public Actor(String name) { 5 this.name = name; 6 } 7 8 public String getName() { 9 return name;10 }11 12 public void setName(String name) {13 this.name = name;14 }15 }实现类1 import java.util.ArrayList; 2 import java.util.stream.Stream; 3 4 public class ActorControl { 5 public static void main(String[] args) { 6 ArrayList<String> man = new ArrayList<>(); 7 ArrayList<String> woman = new ArrayList<>(); 8 9 man.add("刘德华");10 man.add("成龙");11 man.add("周星驰");12 man.add("周润发");13 man.add("李小龙");14 man.add("林正英");15 16 woman.add("林青霞");17 woman.add("关之琳");18 woman.add("朱茵");19 woman.add("林志玲");20 woman.add("林心如");21 woman.add("王祖贤");22 23 //男演员只要名字为3个字的前三人24 Stream<String> manStream = man.stream().filter(s -> s.length() == 3).limit(3);25 //女演员只要姓林的,并且不要第一个26 Stream<String> womanStream = woman.stream().filter(s -> s.startsWith("林")).skip(1);27 //把过滤后的男演员姓名和女演员姓名合并到一起28 Stream<String> stream = Stream.concat(manStream, womanStream);29 //把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据30 stream.map(Actor::new).forEach(s -> System.out.println(s.getName()));31 }32 }或者更简便的写法1 import java.util.ArrayList; 2 import java.util.stream.Stream; 3 4 public class ActorControl { 5 public static void main(String[] args) { 6 ArrayList<String> man = new ArrayList<>(); 7 ArrayList<String> woman = new ArrayList<>(); 8 9 man.add("刘德华");10 man.add("成龙");11 man.add("周星驰");12 man.add("周润发");13 man.add("李小龙");14 man.add("林正英");15 16 woman.add("林青霞");17 woman.add("关之琳");18 woman.add("朱茵");19 woman.add("林志玲");20 woman.add("林心如");21 woman.add("王祖贤");22 23 Stream.concat(man.stream().filter(s -> s.length() == 3).limit(3),woman.stream().filter(s -> s.startsWith("林")).skip(1)).map(Actor::new).forEach(s -> System.out.println(s.getName()));24 }25 }2.4 Stream流的收集操作概念对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。常用方法方法名说明R collect(Collector collector)把结果收集到集合中工具类Collectors提供了具体的收集方式方法名说明public static Collector toList()把元素收集到List集合中public static Collector toSet()把元素收集到Set集合中public static Collector toMap(Function keyMapper,Function valueMapper)把元素收集到Map集合中1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Map; 4 import java.util.Set; 5 import java.util.stream.Collectors; 6 import java.util.stream.Stream; 7 8 public class CollectorsDemo { 9 public static void main(String[] args) {10 List<String> names = new ArrayList<>();11 names.add("张无忌");12 names.add("赵敏");13 names.add("张三丰");14 names.add("张果老");15 names.add("张国立");16 names.add("铁拐李");17 names.add("张赫");18 names.add("张飞");19 Stream<String> nameStream = names.stream().filter(s -> s.length()==3);20 List<String> threeWordsNames = nameStream.collect(Collectors.toList());21 for (String s : threeWordsNames){22 System.out.println(s);23 }24 System.out.println("------");25 Stream<String> namesStreams = names.stream().filter(s ->s.startsWith("张"));26 Set<String> threeNames = namesStreams.collect(Collectors.toSet());27 for (String sm : threeNames){28 System.out.println(sm);29 }30 System.out.println("------");31 String[] strArray = {"1,张曼玉","2,林青霞","3,朱茵"};32 Stream<String> strStream = Stream.of(strArray);33 Map<String,String> bf = strStream.collect(Collectors.toMap(s -> s.split(",")[0],s -> s.split(",")[1]));34 Set<String> keys = bf.keySet();35 for (String key : keys){36 String value = bf.get(key);37 System.out.println(value);38 }39 }40 }来源:https://www.icode9.com/content-1-774751.html