interface接口 的设计目的是面向接口编程,提高扩展性。
Java8中,接口中除了抽象方法外,还可以定义default默认方法和static静态方法。
default修饰的默认方法,属于实例方法,可以被实现类调用或重写。
调用:实现类必须implements接口,才能调用该接口的default默认方法。
重写:实现类implements不同接口时,接口中存在相同签名的方法(名称、参数、类型完全一致),则实现类必须重写该方法,明确方法定义;
static修饰的静态方法,属于类的静态方法。但它不能被子类继承,只能用interface接口名称调用。
public class Demo01 {
public static void main(String[] args) {
// Bird b1 = new Bird();
IFly b1 = new Bird();
b1.fly();
b1.test();
// 接口中的静态方法只能通过interface接口名称调用
IFly.eat();
}
}
//1.java8中的Interface接口
interface IFly {
void fly();
// 接口中默认的方法可以被实现类进行调用,重写
default void test() {
System.out.println("这里是接口中的默认方法");
}
// 接口中被static修饰的方法不能被子类继承,
// 只能通过interface接口名称调用
public static void eat() {
System.out.println("动物喜欢吃动物");
}
}
class Bird implements IFly {
@Override
public void fly() {
System.out.println("小鸟飞的方法");
}
// 可以重写接口中的默认方法
@Override
public void test() {
System.out.println("小鸟自己的test方法");
}
}
Lambda 表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。
使用Lambda 表达式可以使代码变的更加简洁紧凑。
格式:
(parameters)-> expression 或 (parameters)->{ statements;}
示例:
public class Demo02_lambda {
public static void main(String[] args) {
// 匿名内部类
// 定义一个没有名字的类
// 实现Runnable接口重写run方法
// 创建这个类的对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程1执行的代码");
}
}).start();
// lambda写法
new Thread(() -> {
System.out.println("线程2执行的代码");
}).start();
}
}
(parameters)->{statements;}
(参数类型 参数名):抽象方法的参数列表
->:起连接作用
{}:存放方法体的内容,对抽象方法的覆盖/重写--(只能对单一抽象类的抽象方法[函数式])
省略写法:能推导的都可以省略
1.参数的类型可以精简
2.小括号可以省略(参数列表中有且只有一个参数),参数类型省略
3.如果大括号只有一条语句,此时可以省略大括号,return 分号时需要同时省略
interface Swim {
void swimming(int a);
}
public class Demo03_lambda {
public static void main(String[] args) {
goSwim(new Swim() {
@Override
public void swimming(int a) {
System.out.println("匿名内部类的游泳方法重写"+a);
}
});
// lambda写法
// Swim s1 = () -> {
// System.out.println("lambda写法的游泳方法调用");
// };
// goSwim(s1);
goSwim(a -> System.out.println("lambda写法的游泳方法调用"+a));
}
public static void goSwim(Swim s) {
s.swimming(10);
}
}
public class Demo04_lambda {
public static void main(String[] args) {
// list排序
List<Integer> list = Arrays.asList(1, 3, 2, 6, 7, 9, 8, 4, 5);
// Collections.sort(list, new Comparator() {
// @Override
// public int compare(Integer o1, Integer o2) {
// return o1 - o2;
// }
// });
// lambda表达式
// Comparator comparator = (Integer o1, Integer o2) -> {
// return o1 - o2;
// };
// Collections.sort(list, comparator);
Collections.sort(list, (o1, o2) -> o1 - o2);
System.out.println(list);
}
}
public class Test {
public static void main(String[] args) {
List<Person> list = new ArrayList<Person>();
list.add(new Person("张三", 18));
list.add(new Person("李四", 17));
list.add(new Person("王五", 5));
list.add(new Person("任六", 60));
list.add(new Person("刘七", 10));
// list.sort(new Comparator() {
// @Override
// public int compare(Person o1, Person o2) {
// // TODO Auto-generated method stub
// return o1.age - o2.age;
// }
// });
// System.out.println(list);
// lambda表达式写法
// Comparator com=(o1,o2)->o1.age-o2.age;
// list.sort(com);
// list.sort((o1, o2) -> o1.age - o2.age);
Collections.sort(list, (o1, o2) -> o1.age - o2.age);
System.out.println(list);
}
}
class Person {
public String name;
public int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
List<String> langList = Arrays.asList("Basic","QBasic","c","c++","PowerBuilder","Visual Basic");
langList.forEach((name)->{
System.out.println(name);
});
在 Java 8 中专门有一个包放函数式接口java.util.function,该包下的所有接口都有 @FunctionalInterface 注解,提供函数式编程方式。
//lambda函数式编程
public class Demo01 {
public static void main(String[] args) {
int sum = sumMethod(arr -> {
// 重写函数式接口的getSum方法进行求和
int add = 0;
for (int num : arr) {
add += num;
}
return add;
});
System.out.println(sum);
}
public static int sumMethod(sumOperator s) {
int[] arr = { 1, 2, 3, 5, 4, 6, 9, 7, 8 };
int sum = s.getSum(arr);
return sum;
}
}
//自定义内置函数接口
@FunctionalInterface
interface sumOperator {
// 求数组中所有元素的和
int getSum(int[] arr);
}
T get() — 方法没有参数,有返回值,需要对外提供一个符合泛型类型的对象数据
T get();
示例代码:
import java.util.Arrays;
//T get() --- 方法没有参数,有返回值,需要对外提供一个符合泛型类型的对象数据
import java.util.function.Supplier;
public class Demo02AndSupplier {
public static void main(String[] args) {
System.out.println("main中的方法");
printMax(() -> {
System.out.println("Supplier对象的get方法");
int[] arr = { 1, 8, 6, 9, 4, 2, 50 };
Arrays.sort(arr);
return arr[arr.length - 1];
});
}
// 输出数组中的最大元素
public static void printMax(Supplier supplier) {
System.out.println("printMax方法");
int max = supplier.get();
System.out.println(max);
}
}
public class Demo03AndSupplier {
public static void main(String[] args) {
oNum(() -> {
while (true) {
int num = (int) (Math.random() * 100);
if ((num & 1) == 0) {
return num;
}
}
});
}
public static void oNum(Supplier<Integer> supplier) {
int onum = supplier.get();
System.out.println("随机偶数为" + onum);
}
}
void accept(T t);
default Consumer andThen(Consumer after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
示例代码:
public class Demo04AndConsumer {
public static void main(String[] args) {
System.out.println("main方法");
Consumer<String> con1 = a -> System.out.println("我转小写啦" + a.toLowerCase());
Consumer<String> con2 = a -> System.out.println("我转大写啦" + a.toUpperCase());
// 转小写
// toLower(con1, "HHHHHHHHHH");
// 转大写
// toLower(con2, "jjjjjjjjjjj");
// 转大写再转小写
toUpperAndLower(con2, con1, "Stringzhua");
}
// 转小写
public static void toLower(Consumer<String> consumer, String str) {
System.out.println("toLower方法的调用");
consumer.accept(str);
}
// 转大写
public static void toUpper(Consumer<String> consumer, String str) {
System.out.println("toUpper方法的调用");
consumer.accept(str);
}
// 先转大写再转小写
public static void toUpperAndLower(Consumer<String> consumer1, Consumer<String> consumer2, String str) {
// consumer1.accept(str);
// consumer2.accept(str);
System.out.println("转大写再转小写方法的调用");
// 使用默认方法andThen()
// 在消费一个数据时先进行操作1,再进行操作2,实现操作的组合
consumer1.andThen(consumer2).accept(str);
}
}
Function 接口接受一个参数并生成结果。默认方法可用于将多个函数链接在一起(compose, andThen)。
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;
}
示例代码:
//Function --转换型接口
//R apply(T t)
public class Demo05AndFunction {
public static void main(String[] args) {
// 将字符串转换为数字
// Function fun = (s -> Integer.parseInt(s));
// method(fun, "123456");
method(s -> Integer.parseInt(s), "123456");
// 打印字符串长度
method(s -> s.length(), "qwertyuiop");
methodandThen(s -> s.length(), num -> new double[num], "hello");
}
private static void method(Function<String, Integer> fun, String string) {
Integer num = fun.apply(string);
System.out.println(num);
}
// 传入一个字符串转成对用长度的double类型的数组
// 字符串转Integer类型
// 将Integer类型转数组
private static void methodandThen(Function<String, Integer> fun1, Function<Integer, double[]> fun2, String str) {
double[] d = fun1.andThen(fun2).apply(str);
System.out.println(Arrays.toString(d));
}
}
Predicate接口是只有一个参数的返回布尔类型值的 断言型 接口。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与and,或or,非negate):
传入一个参数,返回值为boolean类型
根据传入的参数,进行判断,返回boolean
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 Demo06AndPredicate {
public static void main(String[] args) {
// 判断此数字是否为偶数
Predicate<Integer> predicate = num -> (num & 1) == 0;
int number = 150;
boolean b1 = method(number, predicate);
System.out.println(number + "是否为偶数? " + b1);
// 判断某个数字是否大于100
Predicate<Integer> predicate2 = num -> num >= 100;
boolean b2 = method(number, predicate2);
System.out.println(number + "是否大于100? " + b2);
method(number, predicate, predicate2);
}
private static void method(int num, Predicate<Integer> pre, Predicate<Integer> pre1) {
// 与运算&&
// and方法等价如下
// Predicate predicate = (t) -> {
// return (num & 1) == 0 && num >= 100;
// };
// predicate.test(num);
boolean b = pre.and(pre1).test(num);
System.out.println("与运算后的结果" + b);
// 或运算||
boolean b1 = pre.or(pre1).test(num);
System.out.println("或运算后的结果" + b1);
// 非运算
// negate()方法等价如下:
// Predicate p1 = (t) -> {
// return !pre.test(num);
// };
boolean b2 = pre.negate().test(num);
System.out.println("非运算后的结果" + b2);
}
private static boolean method(int number, Predicate<Integer> predicate) {
boolean b = predicate.test(number);
return b;
}
}
比较器接口,用于比较指定元素值的大小。Java8版本中,添加了多个新的default方法,用于比较器合并、反转等操作。
// 案例数据
List<String> langList = Arrays.asList("Basic", "QBasic","HTML", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#","java");
// 按照ASCII码比较
Comparator<String> comparator1 = (s1, s2) -> {
return s1.compareTo(s2);
};
// 按照长度比较
Comparator<String> comparator2 = (s1, s2) -> {
return s1.length() - s2.length();
};
// 先比较长度,再比较ASCII码
Comparator<String> comparator3 = comparator2.thenComparing(comparator1);
// 在comparator3的基础上,反转条件
Comparator<String> comparator4 = comparator2.reversed();
// 按照指定Comparator,进行排序
langList.sort(comparator2);
java.util.Stream 表示能应用在一组元素上一次执行的操作序列。
Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以连续完成多个操作。
Stream 的创建需要指定一个数据源。
List<String> list = Arrays.asList("Basic", "QBasic","HTML", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#",
"java");
Stream<String> stream = list.stream();
/**
* 返回一个串行流
*/
default Stream<E> stream()
/**
* 返回一个并行流
*/
default Stream<E> parallelStream()
/**
* 返回T的流
*/
public static<T> Stream<T> of(T t)
/**
* 返回其元素是指定值的顺序流。
*/
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
/**
* 过滤,返回由与给定predicate匹配的该流的元素组成的流
*/
Stream<T> filter(Predicate<? super T> predicate);
/**
* 此流的所有元素是否与提供的predicate匹配。
*/
boolean allMatch(Predicate<? super T> predicate)
/**
* 此流任意元素是否有与提供的predicate匹配。
*/
boolean anyMatch(Predicate<? super T> predicate);
/**
* 返回一个 Stream的构建器。
*/
public static<T> Builder<T> builder();
/**
* 使用 Collector对此流的元素进行归纳
*/
<R, A> R collect(Collector<? super T, A, R> collector);
/**
* 返回此流中的元素数。
*/
long count();
/**
* 返回由该流的不同元素(根据 Object.equals(Object) )组成的流。
*/
Stream<T> distinct();
/**
* 遍历
*/
void forEach(Consumer<? super T> action);
/**
* 用于获取指定数量的流,截短长度不能超过 maxSize 。
*/
Stream<T> limit(long maxSize);
/**
* 用于映射每个元素到对应的结果
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
/**
* 根据提供的 Comparator进行排序。
*/
Stream<T> sorted(Comparator<? super T> comparator);
/**
* 在丢弃流的第n个元素后,返回由该流剩余元素组成的流。
*/
Stream<T> skip(long n);
/**
* 返回一个包含此流的元素的数组。
*/
Object[] toArray();
/**
* 使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。
*/
<A> A[] toArray(IntFunction<A[]> generator);
/**
* 合并流
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
public class Stream01 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("一猫人", "一休", "李郁", "李煜", "李鑫德"));
ArrayList<String> namelist = new ArrayList<String>();
// 1.拿到所有姓李的
for (String string : list) {
if (string.startsWith("李")) {
namelist.add(string);
}
}
// 2.拿到名字长度为2的
ArrayList<String> result = new ArrayList<String>();
for (String string : namelist) {
if (string.length() == 2) {
result.add(string);
}
}
// 3.打印数据
System.out.println(result);
list.stream().filter(str -> str.startsWith("李")).filter(str -> str.length() == 2)
.forEach(str -> System.out.println(str));
}
}
获取Stream流的方式
Collection集合接口下的所有实现类都有stram()方法
Stram静态方法of()获取对应的流
package day34_Stream流;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Stream;
//获取Stream流的方式
//Collection集合接口下的所有实现类都有stram()方法
//Stram静态方法of()获取对应的流
public class Stream02 {
public static void main(String[] args) {
// 方式1:获取Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> stream2 = set.stream();
Map<Integer, String> map = new HashMap<Integer, String>();
Stream<Entry<Integer, String>> stream3 = map.entrySet().stream();
// 方式2:Stream.of()
Stream<String> steam1 = Stream.of("aa", "ab", "ac", "bb", "bc");
String[] s1 = { "aa", "ab", "ac", "bb", "bc" };
Stream<String> steam2 = Stream.of(s1);
Integer[] a = { 1, 3, 5, 7, 9, 22 };
Stream<Integer> steam3 = Stream.of(a);
}
}
1.Stream只能操作一次
2.Stream流的方法返回的Stream是一个新的流
3.Stream不调用最终的操作,中间的操作是不会执行
package day34_Stream流;
import java.util.stream.Stream;
public class Stream03 {
public static void main(String[] args) {
Stream<String> s1 = Stream.of("aa", "bb", "cc");
// 1.Stream只能操作一次
// long count = s1.count();
// long count1 = s1.count();
// System.out.println(count);
// System.out.println(count1);
// 2.Stream流的方法返回的Stream是一个新的流
// Stream s2 = s1.limit(3);
// System.out.println(s1);
// System.out.println(s2);
// 3.Stream不调用最终的操作,中间的操作是不会执行
s1.filter((s) -> {
System.out.println(s);
return true;
}).count();
}
}
// foreach方法 遍历元素
// list.stream().forEach((str) -> System.out.println(str));
// count 查看元素个数
// System.out.println(list.stream().count());
// limit() 获取流中的前N个元素
// list.stream().limit(2).forEach((str) -> System.out.println(str));
// skip() 跳过前几个元素
// list.stream().skip(0).forEach((str) -> System.out.println(str));
// map() 将一种流转换为另一种流
// list.stream().map((str) -> str.length()).forEach(a -> System.out.println(a));
// sorted() 进行排序比较
// list.stream().sorted((o1,o2)->o1.compareTo(o2)).forEach(System.out::println);
// list.stream().sorted().forEach(System.out::println);
// allMatch 此流任意元素是否满足断言式接口的内容判断
// boolean b = list.stream().allMatch(str -> str.length() == 4);
// boolean b = list.stream().anyMatch(str -> str.length() == 4);
boolean b = list.stream().noneMatch(str -> str.length() == 4);
System.out.println(b);
// distinct去重,需要Person类重写hashcode和equals方法
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("猫猫头"));
list.add(new Person("一猫人"));
list.add(new Person("猫猫头"));
list.add(new Person("打工猫猫"));
list.add(new Person("摸鱼猫猫"));
list.stream().distinct().forEach(person -> System.out.println(person));
//方法返回值为Stream的为中间操作
//方法返回值为其他类型的是最终操作
public class Stream06 {
public static void main(String[] args) {
List<String> list = Arrays.asList("abc", "deftb", "gkh", "abc");
// 收集是一个 最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map)或 字符串。
// Collectors.toList()
// Collectors.toSet()
// Collectors.toMap()
// 将过滤结果,收集至List集合,默认为ArrayList
List<String> newlist = list.stream().filter(str -> str.contains("b")).collect(Collectors.toList());
System.out.println(newlist);
// 将过滤结果,收集至Set集合,默认为HashSet
Set<String> newSet = list.stream().filter(str -> str.contains("b")).collect(Collectors.toSet());
System.out.println(newSet);
// 将过滤结果,收集至Map集合,默认为HashMap
Map<String, Integer> newMap = list.stream().filter(s -> s.contains("b")).distinct()
.collect(Collectors.toMap(s -> s, s -> s.length()));
System.out.println(newMap);
}
}
过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作。所以过滤后的结果,可以继续进行其它Stream操作(例如forEach,forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作)。
List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
// 返回符合条件的stream流
// 计算流符合条件的stream流的数量
long count = strings.stream().filter(s -> "abc".equals(s)).count();
System.out.println(count);
示例
public class Stream07 {
public static void main(String[] args) {
List<String> list = Arrays.asList("123", "156", "412", "486", "865", "870", "9000");
// collect(Collectors.mapping(,))
// 示例:过滤掉不包含3的,并将其转换为Integer类型的集合
List<Integer> newlist = list.stream().filter(str -> str.contains("3"))
.collect(Collectors.mapping(str -> Integer.parseInt(str), Collectors.toList()));
System.out.println(newlist);
// collect(Collectors.groupingBy(,))
// 示例:按照长度进行分组
// Map> newMap = list.stream()
// .collect(Collectors.groupingBy(s -> s.length(), Collectors.toList()));
Map<Character, List<String>> newMap = list.stream()
.collect(Collectors.groupingBy(s -> s.charAt(0), Collectors.toList()));
System.out.println(newMap);
}
}
排序是一个中间操作,返回的是排序好后的Stream。(不影响原数据)
List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
// 排序并遍历
strings.stream()
.sorted()
.forEach(System.out::println);
映射是一个中间操作, 会将元素根据指定的 Function 接口来依次将元素转成另外的对象。
List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
// 转换字符串为大写,降序后,输出
strings.stream()
.map((item)->{return item.toUpperCase();})
.sorted((s1,s2)->{return s2.compareTo(s1);})
.forEach(System.out::println);
计数是一个 最终操作,返回Stream中元素的个数,返回值类型是 long。
List<String> strings = Arrays.asList("abc", "deft", "gkh", "abc");
// 统计“a”开头的元素个数
long count = strings.stream().filter((s)->s.startsWith("a")).count();
System.out.println(count);
收集是一个 最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map)或 字符串。
将Stream中的元素,收集至新集合
● Collectors.toList()
● Collectors.toSet()
● Collectors.toMap()
示例:过滤Stream中的元素,并将过滤结果收集到一个新的集合(List、Set、Map)
List<String> langList = Arrays.asList("abc", "deft", "gkh", "abc");
// 将过滤结果,收集至List集合,默认为ArrayList
List<String> resultList = langList.stream().filter(s -> s.toUpperCase().contains("B"))
.collect(Collectors.toList());
System.out.println(resultList);
// 将过滤结果,收集至LinkedList集合
LinkedList<String> resultLinkedList = langList.stream().filter(s -> s.toUpperCase().contains("B"))
.collect(Collectors.toCollection(LinkedList::new));
System.out.println(resultLinkedList);
// 将过滤结果,收集至Set集合,默认为HashSet
Set<String> resultSet = langList.stream().filter(s -> s.toUpperCase().contains("B"))
.collect(Collectors.toSet());
System.out.println(resultSet);
// 将过滤结果,收集至Map集合,默认为HashMap--
Map<String, Integer> resultMap = langList.stream().filter(s -> s.toUpperCase().contains("B")).distinct()
.collect(Collectors.toMap(s -> s, s -> s.length()));
System.out.println(resultMap);
将Stream中的元素,映射后,收集至新集合
Collectors.mapping()
示例:对Stream中的每个元素进行映射,并将映射结果收集到一个新的集合(List)
// 将字符串集合中的每个字符串,映射转换为Integer
List<String> numberStrings = Arrays.asList("4344","6641","3432","6432","6423","9423");
List<Integer> numberList = numberStrings.stream()
.collect(Collectors.mapping(s->Integer.parseInt(s), Collectors.toList()));
System.out.println(numberList);
将Stream中的元素,分组后,收集至Map集合
Collectors.groupingBy()
示例:对Stream中的每个元素进行分组统计,并将统计结果收集到一个新的集合(Map)
List<String> langList = Arrays.asList("abc", "deft", "gkh", "abc");
// 按照字符数统计
Map<Integer, List<String>> resultMap1 = langList.stream().collect(Collectors.groupingBy(s -> s.length()));
System.out.println(resultMap1);
// 按照首字母统计
Map<Character, List<String>> resultMap2 = langList.stream()
.collect(Collectors.groupingBy(s -> s.toLowerCase().charAt(0)));
System.out.println(resultMap2);
统计是一个最终操作,返回Stream中元素的各类统计信息,返回值类型是 XXXConsumer。
List<Integer> number = Arrays.asList(1, 2, 5, 4);
//mapToInt将一个流中的元素转换为 int 类型
IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : "+statistics.getMax());
System.out.println("列表中最小的数 : "+statistics.getMin());
System.out.println("平均数 : "+statistics.getAverage());
System.out.println("所有数之和 : "+statistics.getSum());
Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。
示例:排序
准备示例数据
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.nanoTime();//返回豪微秒
long count = values.stream().sorted().count();
System.out.println(count);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("串行排序,耗时共计: %d 毫秒", millis));
串行排序,耗时共计591毫秒
并行排序
long t0 = System.nanoTime();
long count = values.parallelStream().sorted().count();
System.out.println(count);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("并行排序,耗时共计: %d 毫秒", millis));
//并行流
public class Stream08 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
// 方式1:parallelStream()
Stream<String> stream1 = arrayList.parallelStream();
// 方式2:先获取普通的串行流,再将串行流转并行流parallel()
Stream<String> stream2 = arrayList.stream().parallel();
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 0).parallel().filter(num -> {
System.out.println(Thread.currentThread().getName() + "@" + num);
return true;
}).count();
}
}
并行排序,耗时共计283毫秒
使用并行流往其他集合中添加元素会发生线程安全问题
package day34_Stream流;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collector;
import java.util.stream.Collectors;
public class Stream09 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 1000; i++) {
list.add(i);
}
// 使用并行流往其他集合中添加元素会发生线程安全问题
// ArrayList newlist = new ArrayList();
// list.stream().parallel().forEach(num -> newlist.add(num));
// System.out.println(newlist.size());
// 解决方案1:加锁
// ArrayList newlist = new ArrayList();
// Object object = new Object();
// list.stream().parallel().forEach(num -> {
// synchronized (object) {
// newlist.add(num);
// }
// });
// System.out.println(newlist.size());
// 解决方案2:使用线程安全的集合
// Vector newlist = new Vector();
// list.stream().parallel().forEach(num -> {
// newlist.add(num);
// });
// System.out.println(newlist.size());
// 解决方案3:转成集合
List<Integer> newlist = list.stream().parallel().collect(Collectors.toList());
System.out.println(newlist.size());
}
}
函数式接口总结
1.Predicate、Function、Consumer、Comparator
2.通过链式编程,使得它可以方便地对数据进行链式处理。
3.方法参数都是函数式接口类型。
4.一个 Stream 只能操作一次,操作完就关闭了,继续使用这个 Stream 会报错。
5.Stream 不保存数据,不改变数据源。
//Format yyyy-MM-dd
LocalDate date = LocalDate.now();
System.out.println(String.format("Date format : %s", date));
//Format HH:mm:ss
LocalTime time = LocalTime.now().withNano(0);
System.out.println(String.format("Time format : %s", time));
//Format yyyy-MM-dd HH:mm:ss
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateTimeStr = dateTime.format(dateTimeFormatter);
System.out.println(String.format("DateTime Format : %s", dateTimeStr));
LocalDate date1 = LocalDate.of(2021, 1, 26);
LocalDate date2 = LocalDate.parse("2021-01-26");
System.out.println(date1);
System.out.println(date2);
LocalDateTime dateTime1 = LocalDateTime.of(2021, 1, 26, 12, 12, 22);
LocalDateTime dateTime2 = LocalDateTime.parse("2021-01-26T12:12:22");
System.out.println(dateTime1);
System.out.println(dateTime2);
LocalTime time1 = LocalTime.of(12, 12, 22);
LocalTime time2 = LocalTime.parse("12:12:22");
System.out.println(time1);
System.out.println(time2);
// 计算一周后的日期
LocalDate localDate = LocalDate.now();
// 方法1
LocalDate after1 = localDate.plus(1, ChronoUnit.WEEKS);
System.out.println("一周后日期:" + after1);
// 方法2
LocalDate after2 = localDate.plusWeeks(1);
System.out.println("一周后日期:" + after2);
// 计算两个日期间隔多少天,计算间隔多少年,多少月
LocalDate date1 = LocalDate.parse("2021-02-26");
LocalDate date2 = LocalDate.parse("2021-12-23");
Period period = Period.between(date1, date2);
System.out.println("date1 到 date2 相隔:" + period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天");
// 计算两个日期间隔多少天
long day = date2.toEpochDay() - date1.toEpochDay();
System.out.println(date2 + "和" + date2 + "相差" + day + "天");
LocalDate today = LocalDate.now();
// 获取当前月第一天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("当前月第一天:" + firstDayOfThisMonth);
// 获取本月最后一天
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("本月最后一天:" + lastDayOfThisMonth);
// 获取下一天:
LocalDate nextDay = lastDayOfThisMonth.plusDays(1);
System.out.println("下一天(次月第一天):" + nextDay);
// 获取当年最后一天
LocalDate lastday = today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("当前月第一天:" + lastday);
// 获取当年最后一个周日
LocalDate lastMondayOfThisYear = lastday.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
System.out.println("当年最后一个周日:" + lastMondayOfThisYear);