Java8 新特性总结

Java8新特性

Java8中的interface接口

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 表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。
使用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<Integer>() {
//			@Override
//			public int compare(Integer o1, Integer o2) {
//				return o1 - o2;
//			}
//		});
		// lambda表达式
//		Comparator<Integer> 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<Person>() {
//			@Override
//			public int compare(Person o1, Person o2) {
//				// TODO Auto-generated method stub
//				return o1.age - o2.age;
//			}
//		});
//		System.out.println(list);

		// lambda表达式写法
//		Comparator<Person> 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);
});

lambda函数式编程

在 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);
}

Supplier — 供给型接口

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<Integer> 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);
	}
}

Consumer – 消费者接口

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 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<T, R> --转换型接口

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<T, R> --转换型接口
//R apply(T t)
public class Demo05AndFunction {
	public static void main(String[] args) {
		// 将字符串转换为数字
//		Function<String, Integer> 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 boolean test(T t);

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<Integer> 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<Integer> 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;
	}
}

Comparator接口

比较器接口,用于比较指定元素值的大小。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);

Stream流

java.util.Stream 表示能应用在一组元素上一次执行的操作序列。
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)
示例1
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));
	}
}
示例2

获取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);
	}
}
示例3

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<String> s2 = s1.limit(3);
//		System.out.println(s1);
//		System.out.println(s2);

//		3.Stream不调用最终的操作,中间的操作是不会执行
		s1.filter((s) -> {
			System.out.println(s);
			return true;
		}).count();
	}
}
示例4
        // 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));
示例5
//方法返回值为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);
	}
}

Filter 过滤

过滤通过一个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<Integer, List<String>> 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);
	}
}

Sorted 排序

排序是一个中间操作,返回的是排序好后的Stream。(不影响原数据)

List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
	    
// 排序并遍历
strings.stream()
        .sorted()
        .forEach(System.out::println);

Map 映射

映射是一个中间操作, 会将元素根据指定的 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);

Count 计数

计数是一个 最终操作,返回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);

Collect收集

收集是一个 最终操作,返回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);

Statistics 统计

统计是一个最终操作,返回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());

Parallel Streams 并行流

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<Integer> newlist = new ArrayList<Integer>();
//		list.stream().parallel().forEach(num -> newlist.add(num));
//		System.out.println(newlist.size());

		// 解决方案1:加锁
//		ArrayList<Integer> newlist = new ArrayList<Integer>();
//		Object object = new Object();
//		list.stream().parallel().forEach(num -> {
//			synchronized (object) {
//				newlist.add(num);
//			}
//		});
//		System.out.println(newlist.size());

		// 解决方案2:使用线程安全的集合
//		Vector<Integer> newlist = new Vector<Integer>();
//		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);
  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值