import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; /** * 注意:源发行版1.8需要目标发行版1.8所以需要到setting中去设置java compiler * 1.Lambda表达式取代了匿名类,取消了模板,它将允许我们将行为传到函数里,lambda在java中又叫做匿名函数或则闭包 * Lambda方法在编译器内部被翻译成私有方法,并派发 invokedynamic 字节码指令来进行调用 * 2.stream函数式操作流元素集合 */ public class practicejdk8<T> { public static void main(String[] args) { /**********************************lambda表达式************************************/ System.out.println("java泛型" + new practicejdk8<String>().getList()); /** * 1.lamda表达式替换传统的开启线程的方式 */ //传统 new Thread(new Runnable() { public void run() { System.out.println("传统的通过runable实现开启线程的方式"); } }).start(); //jdk8 new Thread(() -> System.out.println("jdk8采用的通过runable开启线程的方式")).start(); /** * 2.lamda表达式进行事件处理,例如swing中的事件监听代码 */ //传统 JButton show = new JButton("showButton"); show.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("传统方式完成事件监听"); } }); //jdk8 show.addActionListener((e) -> { System.out.println("jdk8采用的方式完成事件监听"); }); /** *3.使用lambda表达式对列表进行迭代 */ //传统 List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API"); for (Object feature : features) { System.out.print("传统方式遍历集合:" + feature + "\n"); } //jdk8 features.forEach(n -> { System.out.print("jdk8遍历集合:" + n + "\n"); }); /** * 场景4.支持函数式接口Predicate */ List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp"); filter(languages, (str) -> str.toString().length() > 4); /** * 场景5.新的map reduce */ List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500); //传统方式 for (Integer cost : costBeforeTax) { double price = cost + 0.12 * cost; System.out.println(price); } //jdk8方式 System.out.println("======================"); costBeforeTax.stream().map((cost) -> cost + 0.12 * cost).forEach((cos) -> { System.out.println(cos); }); double bill = costBeforeTax.stream().map((cost) -> cost + 0.12 * cost).reduce((sum, cost) -> sum + cost).get(); System.out.printf("total:" + bill); /** * 场景6.通过过滤创建一个String列表 */ List<String> stringList = Arrays.asList("try", "to", "do", "what you want"); List<String> filtered = stringList.stream().filter((x) -> x.length() > 2).collect(Collectors.toList()); System.out.printf("Original List : %s, filtered list : %s %n", stringList, filtered); /** * 场景7.对列表的每个元素利用函数 */ List<String> beautyWords = Arrays.asList("memories", "beautiful", "very", "hurt", "memories", "memories of the past", "but", "can", "not", "go", "back"); String words = beautyWords.stream().map((x) -> x.toUpperCase()).collect(Collectors.joining(" ")); System.out.println("回忆很美,很伤,回忆只是回不到过去的记忆" + words); /** * 场景8.利用distinct对集合列表去重,创建一个子列表 */ List<String> distinctWords = beautyWords.stream().map((x) -> x.toLowerCase()).distinct().collect(Collectors.toList()); System.out.println(distinctWords); /** * 场景9.利用IntSummaryStatistics计算集合中的最大值,最小值,总和以及平均值 */ List<Integer> prime = Arrays.asList(1, 3, 5, 7, 9, 11, 13, 17, 19); IntSummaryStatistics statistics = prime.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("当前集合中最大值是:" + statistics.getMax() + ",最小值:" + statistics.getMin() + ",总共的数字:" + statistics.getCount() + ",平均数:" + statistics.getAverage() + ",总和:" + statistics.getSum()); /**********************************Stream函数式操作流元素集合************************************/ List<Integer> nums = Arrays.asList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10); System.out.println("求和:" + nums.stream() .filter((x) -> x != null) //过滤 .distinct() //去重 .mapToInt((num) -> num * 1) //map操作 .skip(2) //跳过前二条数据 .limit(4) //取前四条数据 .sum()) //求和 ; /**********************************方法引用************************************/ //方法引用使用一对冒号 :: person p = new person("zhang", "男"); person p2 = new person("chao", "男"); List<person> personList = Arrays.asList(p, p2); personList.forEach(person -> System.out.println(person.getName())); personList.forEach(person::getName); /**********************************接口的默认方法************************************/ formula f = new formula() { @Override public double calculate(int a) { return a; } }; System.out.println(f.sqrt(4)); /**********************************函数式接口配合lambda表达式使用*********************************** *每一个lambda表达式都对应一个类型,通常是接口类型,并且方法类型和参数通吃是模板类型 * 而“函数式接口”是指仅仅只包含一个抽象方法的接口 * 每一个该类型的lambda表达式都会被匹配到这个抽象方法 * 因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法 */ Converter<String, Integer> stringIntegerConverter = (from) -> Integer.valueOf(from); Integer converted = stringIntegerConverter.convert("123"); System.out.println(converted); /****************************************各种函数式接口总结******************************************/ //predicate接口 Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false //function Function<String, Integer> toInteger = Integer::valueOf; Function<String, String> backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); //supplier接口 Supplier<person> personSupplier = person::new; System.out.println(personSupplier.get().toString()); //Consumer 接口 Consumer<person> greeter = (a) -> System.out.println("Hello, " + a.getName()); greeter.accept(new person("Luke", "男")); //Comparator 接口 Comparator<person> personComparator = (po1, po2) -> po1.getName().compareTo(po2.getName()); person p1 = new person("a", "女"); int isP1MoreP2 = personComparator.compare(p1, p2); int isP2MoreP1 = personComparator.reversed().compare(p1, p2); System.out.println(isP1MoreP2 + "," + isP2MoreP1); //Optional 接口 //此接口不是函数式接口而是一个用来防止空指针异常的辅助类 Optional<String> optional = Optional.of("ask"); System.out.println(optional.isPresent()); //filter接口 // 过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作, // 所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要 // 一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作。 languages.stream().map((m)->m.toLowerCase()).filter((s)->s.startsWith("ja")).forEach(System.out::println); //sort接口 //需要注意的是排序只创建了一个排列好的stream,而不会影响原有的数据 languages.stream().sorted().forEach((x)-> System.out.println(x)); System.out.println(languages); //map映射 //中间操作map将元素根据指定的Function接口来依次将元素转成另外的对象 System.out.println("map映射"); languages.stream().map(String::toUpperCase).sorted((a,b)->b.compareTo(a)).forEach(System.out::println); //match匹配 boolean anyStartsWithA=languages.stream().anyMatch((s)->s.startsWith("J")); System.out.println(anyStartsWithA); System.out.println(languages.stream().allMatch((s)->s.length()>5)); System.out.println(languages.stream().noneMatch((s)->s.equals("Javas"))); //count 计数 System.out.println(languages.stream().filter(s->s.length()>4).count()); //reduce规约 //这是一个最终操作,允许通过指定的函数来讲stream中的多个元素规约为一个元素,规越后的结果是通过Optional接口表示的 Optional<String> reduced=languages.stream().reduce((s1,s2)->s1+","+s2); reduced.ifPresent(System.out::print); System.out.println(languages.stream().reduce((s1,s2)->s1+","+s2).get()); //并行streams,可以发现parallelStream比stream快了50%多 //parallelStream 只是做到别浪费cpu,假如本身电脑cpu的负载很大,那还到处用parallel,那并不能起到作用 //不要在多线程中使用parallelStream,原因同上类似,大家都抢着cpu是没有提升效果,反而还会加大线程切换开销 //会带来不确定性,请确保每条处理无状态且没有关联 //考虑nq模型:n可用的数据量,q针对每个数据元素执行的计算量乘积 N*Q 越大,就越有可能获得并行提速。N x Q > 10000 就会获得有效提升 int max = 1000000; List<String> values = new ArrayList<>(max); for (int i = 0; i < max; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } long t0=System.currentTimeMillis();//串行 values.stream().sorted().count(); long t1=System.currentTimeMillis(); System.out.println("串行排序所花的时间:"+(t1-t0)); long t2=System.currentTimeMillis();//并行 values.parallelStream().sorted().count(); long t3=System.currentTimeMillis(); System.out.println("串行排序所花的时间:"+(t3-t2)); //Map,map类型不支持stream Map<Integer,String> map=new HashMap<>(); for(int i=0;i<10;i++){ map.putIfAbsent(i,"val"+i);//putIfAbsent 不需要我们做额外的存在性检查 } map.forEach((id,val)-> System.out.println(val)); map.merge(11,"张超",(value,newValue)->value.concat(newValue)); //map合并,Merge做的事情是如果键名不存在则插入,否则则对原键对应的值做合并操作并重新插入到map中 System.out.println(map.get(11)); /**********************************Annotation 注解************************************/ } public static void filter(List<String> list, Predicate predicate) { for (String name : list) { if (predicate.test(name)) { System.out.println(name + " "); } } } /** * 集合泛型的示例 * * @return */ public List<T> getList() { List<String> list = new CopyOnWriteArrayList<String>(); list.add("1"); return (List<T>) list; } interface formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } //函数式接口 @FunctionalInterface interface Converter<F, T> { T convert(F from); } }