此笔记来自于B站黑马程序员 good
Java 历史版本及其优势
函数式编程, Stream API
一.函数伊始函数、函数对象
函数对象
行为参数法
延迟执行
a-lambda
b-方法引用
复习小测
- Math::random
() -> Math.random() - Math::sqrt
(double number) -> Math.sqrt(number) - Student::getName
(student stu) -> stu.getName() - Student::setName
(Student stu,String newName) -> stu.setName(newName) - Student::hashcode
(student stu) -> stu.hashcode() - Student::equals
(Student stu, object o) -> stu.equals(o)
假设已有对象 Student stu = new Student(“张三”);
- stu::getName
() -> stu.getName()
- stu::setName
(String newName) -> stu.setName(newName)
- Student::new
(String name) -> new Student(name)
二.函数编程语法 Lambda、方法引用、闭包、柯里化、高阶函数
函数对象类型
import java.util.List;
import java.util.function.Function;
import java.math.BigInteger;
import java.util.ArrayList;
public class CategoryTest {
static class Student{
private String name;
public Student(String name) {
this.name = name;
}
public String getName() { return name; }
public void setName(String name) {this.name=name;}
@Override
public boolean equals(object o){...}
@0verride
public int hashCode() { return Objects.hash(name);}
}
public static void main(String[] args) {
IntPredicate(int a) -> (a & 1) == 0;
IntPredicate(int a) -> BigInteger.valueOf(a).isProbablePrime(100);
(int a, int b, int c) -> a + b + c;
IntBinaryOperator(int a, int b) -> a - b;
IntBinaryOperator(int a, int b) -> a * b;
Supplier<Student>() -> new Student();
Supplier<List<Student>>() -> new ArrayList<Student>();
Function<Studetn, String> obj8 <String, Student> obj8 = (Student s) -> s.getName();
Function<Student, Integer> obj9 (Type7)<Integer, Student> obj9 = (Student s) -> s.getAge();
}
@FunctionalInterface
interface Type1 {
boolean op(int a); // 只能有一个抽象方法
}
@FunctionalInterface
interface Type7<O, I> {
O op(I input);
}
}
常见的函数接口
使用函数接口来解决问题
public class test04 {
public static void main(String[] args) {
List<Integer> result = supply(5, () -> ThreadLocalRandom.current().nextInt());
System.out.println(result);
}
static List<Integer> filter(List<Integer> list, Predicate<Integer> predicate) { ... };
static List<String> map(List<Integer> list, Function<Integer, String> func) { ... };
static void consume(List<Integer> list, Consumer<Integer> consumer) { ... }
static List<Integer> supply(int count, Supplier<Integer> supplier) {
List<Integer> result = new ArrayList<>();
for (int i = 0; i < count; i++) {
// 生成:随机数,但以后可能改变生成规则
result.add(supplier.get());
}
return result;
/**
() -> ThreadLocalRandom.current().nextInt();
*/
}
}
方法引用
类名:静态方法
public class MethodRef1 {
public static void main(String[] args) {
/*
需求:挑选出所有男性学生
*/
Stream.of (
new Student("张无忌", "男"),
new Student("周芷若", "女"),
new Student("宋青书","男")
)
// .filter(stu -> stu.sex().equals("男")); lambda 表达式方式
.filter(MethodRef1::isMale);
// .forEach(sut -> System.out.println(sut)) lambda 表达式方式
.forEach(MethodRef1::abc); // 静态方法引用方式
/*
(Student stu) -> stu.sex().equals("男")
(Student stu) -> MethodRef1.isMale(stu)
*/
public static boolean isMale(Student stu) {
return stu.sex().equals("男");
}
public static void abc(Student stu) {
System.out.println(stu);
}
}
}
类名:非静态方法
public class MethodRef1 {
public static void main(String[] args) {
/*
需求:挑选出所有男性学生
*/
Stream.of (
new Student("张无忌", "男"),
new Student("周芷若", "女"),
new Student("宋青书","男")
)
// .filter(stu -> stu.sex().equals("男")); lambda 表达式方式
.filter(MethodRef1::isMale);
// .forEach(sut -> System.out.println(sut)) lambda 表达式方式
// .forEach(MethodRef1::abc); // 静态方法引用方式
.forEach(Student::print);
/*
(Student stu) -> stu.sex().equals("男")
(Student stu) -> MethodRef1.isMale(stu)
*/
public static boolean isMale(Student stu) {
return stu.sex().equals("男");
}
public static void abc(Student stu) {
System.out.println(stu);
}
record Student(String name, String sex) {
public void print() {
System.out.println(this);
}
/**
* Student::print
* (stu) -> stu.print()
*/
}
}
}
public class MethodRef3 {
static class Util {
public boolean isMale(Student stu) {
return stu.sex().equals("男");
}
}
public static void main(String[] args) {
Util uitl = new Util();
Stream.of (
new Student("张无忌", "男"),
new Student("周芷若", "女"),
new Student("宋青书","男")
)
.filter(util::isMale)
.map(Student::getName)
.forEach(System.out::println);
}
/**
* (stu) -> util.isMale(stu)
*/
record Student(String name, String sex) {
public String getName() {
return this.name;
}
/**
* Student::name
* stu -> stu.name()
*/
}
}
构造方法
import java.util.function.Supplier;
@toString
public class MethodRef4 {
static class Student {
private final String name;
private final Integer age;
public Student() { ... }
public Student(String name) { this.name = name }
public Student(String name, Integer age) {this.name = name; this.age = age}
@Override
public String toString() {
}
}
public static void main(String[] args) {
Supplier<Student> s1 = Student::new;
Function<String, Student> s2 = Student::new;
BiFunction<String, Integer, Student> s3 = Student::new;
System.out.println(s1.get());
System.out.println(s2.apply("张三"));
System.out.println(s3.apply("李四", 25));
}
}
public class MethodRef5 {
public static void main(String[] args) {
Util util = new UtilExt();
util.hiOrder(Stream.of (
new Student("张无忌", "男"),
new Student("周芷若", "女"),
new Student("宋青书","男")
));
}
record Student(String name, String sex) { }
static class Util {
// 过滤男性学生并打印
private bollean isMale(Student stu) {
return stu.sex().equals("男");
}
private boolean isFemale(Student stu) {
return stu.sex().equals("女");
}
void hiOrder(Stream<Student> stream) {
stream
// .filter(stu->this.isMale(stu))
.filter(this.isMale)
.forEach(System.out::println);
}
}
static class UtilExt extends Util {
// 过滤女性学生并打印
void hiOrder(Stream<Student> stream) {
stream
.filter(super::isFemale)
.forEach(System.out::println);
}
}
}
对于无需返回值的函数接口,例如 Consumer 和 Runnable 它们可以配合有返回值的函数对象使用
import java.util.function.Consumer;
public class MethodRef7 {
public static void main(String[] args) {
Consumer<Object> x = MethodRef7::print1;
Function<Object, Integer> y = MethodRef7::print2;
Consumer<Object> z = MethodRef7::print2;
static void print1(Object obj) {
System.out.println(obj);
}
static int print2(Object obj) {
System.out.println(obj);
return 1;
}
}
}
public class Exercise4 {
record Student(String name) { }
// 写出与下列 lamdba表达式 等价的方法引用
public static void main(String[] args) {
Function<String, Integer> lambda1 = Integer::parseInt;
// Function<String, Integer> lambda = (String s) -> Integer.parseInt(S);
// BiPredicate<List<String>, String> lambda2 = (list, element) -> list.contains(element);
BiPredicate<List<String>, String> lambda2 = List::contains;
// BiPredicate<Student, Object> lambda3 = (stu, obj) -> stu.equals(obj);
BiPredicate<Student, Object> lambda3 = Student::equals;
// Predicate<File> lambda4 = (file) -> file.exists();
Predicate<File> lambda4 = File::exists;
// Runtime runtime = Runtime.getRuntime();
// Supplier<Long> lambda5 = () -> runtime.freeMemory();
Supplier<Long> lambda5 = Runtime.getRuntime()::freeMemory;
}
}
例二
public class Exercise5 {
record Color(Integer red, Integer green, Integer blue) { }
// 如果想用 'Color::new' 来构造 Color 对象,还应当补充哪些代码
public static void main(Stirng[] args) {
TrenaryFunction lambda = Color::new; // (Integer, Integer, Integer) -> Color
Color white = lambda.create(255, 255, 255);
System.out.println(white);
}
@FunctionalInterface
interface TernaryFunction {
Color create(Integer red, Integer green, Integer blue);
}
}
public class Exercise6 {
/**
* 传入参数时,分别用
* 类名::静态方法
* 类名::非静态方法
* 来表示 [学生年龄大于等于18] 的条件
*/
static void highOrder(Predicate<Student> predicate) {
List<Student> list = List.of(
new Student("张三", 18),
new Student("张三", 17),
new Student("张三", 20)
);
for (Student stu : list) {
if (predicate.test(stu)) {
System.out.println(stu + "通过测试");
}
}
record Student(String name, int age) {
boolean abc() {
return this.age() >= 18;
}
}
static boolean ageGreaterOrEquals18(Student student) {
return studetn.age() >= 18;
}
public static void main(String[] args) {
highOrder(Exercise6::abc);
/**
* (Exercise6 obj, Student student) -> obj.abc(student)
*/
}
}
}
闭包
public class ClosureTest1 {
@FunctionalInterface
interface Lambda {
int op(int y);
}
static void highOrder(Lambda lambda) { System.out.println(lambda.op(1)); }
public static void main(String[] args) {
/**
*
* 函数对象 (int y) -> x + y 与它外部的变量 x 形成闭包
* effective final <===> final
*/
final int x = 10;
highOrder((int y) -> x + y);
stu.d = 40;
highOrder(lambda);
}
static int a = 1;
int b = 2;
static class Student {
int d;
public Student(int d) {
this.d = d;
}
}
public static void test(int c) {
highOrder(y -> a + y);
highOrder(y -> b + y);
highOrder(y -> c + y);
}
}
public class ClosureTest2 {
public static void main(String[] args) throws IOException {
// 闭包作用:给函数对象提供参数以外的数据
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
int k = i + 1;
Runnable task = () -> System.out.println(Thread.currentThread() + "执行任务" + k);
list.add(task);
}
ExecutorService service = Executors.newVirtualThreadPerTaskExcutor();
for (Runnable task : list) {
service.submit(task);
}
System.in.read();
}
}
public class CarryingOTest {
@FunctionalInterface
interface F2 {
int op(int a, int b);
}
@FunctionalInterface
interface Fa {
Fb op(int a);
}
@FunctionalInterface
interface Fb {
int op(int b);
}
public static void main(String[] args) {
// 两个参数的函数对象
F2 f2 = (a, b) -> a + b;
System.out.println(f2.op(10, 20));
/**
* 改造
* (a) -> 返回另一个参数
* (b) -> a + b
*/
Fa fa = (a) -> (b) -> a + b;
Fb fb = fa.op(10);
int r = fb.op(20);
System.out.println(r);
}
}
示例二
import java.util.ArrayList;
import java.util.List;
public class Carrying1Test {
@FunctionalInterface
interface Fa {
Fb op(List<Integer> a);
}
@FunctionalInterface
interface Fb {
Fc op(List<Interger> b);
}
@FunctionalInterface
interface Fc {
List<Integer> op(List<Integer> c);
}
static Fc step2(Fb fb) {
List<Integer> y = List.of(4, 5, 6);
return fb.op(y);
}
static void step3(Fc fc) {
List<Integer> z = List.of(7, 8, 9);
List<Integer> result = fc.op(z);
System.out.println(result);
}
public static void main(String[] args) {
step3(step2(step1()));
}
}
高阶函数
所谓高阶,就是指它是其它函数对象的使用者
- 将通用、复杂的逻辑隐含在高阶函数内
- 将易变、未定的逻辑放在外部的函数对象中
public class InnerLoop {
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);
// 需求:逆序遍历集合,只想负责元素处理,不改变集合
hiOrder(list, (value) -> System.out.println(value));
}
public static void void hiOrder(List<Integer> list, Consumer<Integer> consumer) {
ListIterator<Integer> iterator = list.listInterator(list.size());
while (iterator.hasPrevious()) {
Integer value = iterator.previous();
consumer.accept(value);
}
}
}
import java.util.LinkedList;
public class BinaryTree {
public record TreeNode(int value, TreeNode left, TreeNode right) {
public String toString() { return "%d".formatted(value); }
}
enum Type {
PRE, IN, POST
}
public static void traversal(TreeNode root, Type type, Consumer<TreeNode> consumer) {
// 用来记住回去的路
LinkedList<TreeNode> stack = new LinkedList<>();
// 当前节点
TreeNode curr = root;
// 记录最近一次处理完的节点
TreeNode last = null;
while (curr != null || !stack.isEmpty()) {
// 左边未走完
if (curr != null) {
// 记住来时的路
stack.push(curr);
if (type == Type.PRE) {
consumer.accept(curr);
}
// 下次向左走
curr = curr.left;
} else {
TreeNode peek = stack.peek();
if (peek.right == null) {
if (type == Type.IN || type == Type.POST) {
consumer.accept(peek);
}
last = stack.pop();
} else if (peek.right == last) {
if (type == Type.POST) {
consumer.accept(peek);
}
last = stack.pop();
} else {
if (type == Type.POST) {
consumer.accept(peek);
}
curr = peek.right;
}
}
}
}
public static void main(String[] args) {
/*
1
/ \
2 3
/ / \
4 5 6
*
*/
TreeNode root = new TreeNode(
new TreeNode(2, new TreeNode(4, null, null), null),
new TreeNode(3, new TreeNode(5, null, null), new TreeNode(6, null, null))
);
traversal(root, Type.PRE, System.out::print);
System.out.println();
traversal(root, Type.IN, System.out::print);
System.out.println();
traversal(root, Type.POST, System.out::print);
System.out.println();
}
}
stream
import java.util.Collection;
import java.util.List;
public class SimpleStream<T> {
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5);
SimpleStream.of(list)
.filter(x -> (x & 1) == 1)
.map(x -> x * x)
.forEach(System.out::println);
}
public static <T> SimpleStream<T> of(Collection<T> collection) {
return new SimpleStream<>(Collection);
}
private Collection<T> collection;
private SimpleStream(Collection<T> collection) {
this.collection = collection;
}
public SimpleStream filter(Predicate<T> predicate) {
List<T> result = new ArrayList<>();
for (T t : collection) {
if (predicate.test(t)) {
result.add(t);
}
}
return new SimpleStream<>(result);
}
public <U> SimpleStream<U> map(Function<T, U> function) {
List<U> result = new ArrayList<>();
for (T t : collection) {
U u = function.apply(t);
result.add(U);
}
return new SimpleStream<>(result);
}
public void forEach(Consumer<T> consumer) {
for (T t : collection) {
consumer.accept(t);
}
}
}
import java.util.Collection;
import java.util.List;
public class SimpleStream<T> {
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5);
HashSet<Integer> collect = SimpleStream.of(list)
.collect(HashSet::new, HashSet::add); // HashSet::add (set, t) -> set.add(t)
System.out.println(collect);
StringBuilder collect2 = SimpleStream.of(list).collect(StringBuilder::new, StringBuilder::append);
System.out.println(collect2);
SimpleStream.of(list).collect(() -> new StringJoiner("-"), (joiner, t) -> joiner.add(String.valueOf(t)));
SimpleStream.of(list)
.map(t->String.valueOf(t))
.collect(()->new StringJoiner("-"), StringJoiner::add);
System.out.println(collect3);
// (StringJoiner, Integer) -> void
// (StringJoiner, CharSequence) -> void
SimpleStream.of(list)
.filter(x -> (x & 1) == 1)
.map(x -> x * x)
.forEach(System.out::println);
System.out.println(SimpleStream.of(list).reduce(0, Integer::sum));
System.out.println(SimpleStream.of(list).reduce(Integer.MAX_VALUE, Math::min));
System.out.println(SimpleStream.of(list).reduce(Integer.MIN_VALUE, Math.max));
}
public static <T> SimpleStream<T> of(Collection<T> collection) {
return new SimpleStream<>(Collection);
}
private Collection<T> collection;
private SimpleStream(Collection<T> collection) {
this.collection = collection;
}
// C 代表容器类型,supplier 用来创建容器
public <C> C collect(Supplier<C> supplier, BiConsumer<C, T> consumer) {
C c = supplier.get(); //创建了容器
for (T t : collection) {
consumer.accept(c, t); // 向容器中添加元素
}
return c;
}
// 新增
public T reduce(T o, BinaryOperator<T> operator) {
T p = o;
for (T t : collection) { // t是本次遍历的元素
p = operator.apply(p, t); // 累加器
}
return p;
}
public SimpleStream filter(Predicate<T> predicate) {
List<T> result = new ArrayList<>();
for (T t : collection) {
if (predicate.test(t)) { // 过滤器
result.add(t);
}
}
return new SimpleStream<>(result);
}
public <U> SimpleStream<U> map(Function<T, U> function) {
List<U> result = new ArrayList<>();
for (T t : collection) {
U u = function.apply(t);
result.add(U);
}
return new SimpleStream<>(result);
}
public void forEach(Consumer<T> consumer) {
for (T t : collection) {
consumer.accept(t); // 遍历
}
}
}
public class SimpleStream<T> {
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5, 1, 2, 3);
/*
key value
1 1
2 2
3 2
4 1
5 1
*/
HashMap<Integer, Integer> collect = SimpleStream.of(list)
.collect(HashMap::new, (map, t) -> {
if (!map.containsKey(t)) {
map.put(t, 1);
} else {
Integer v = map.get(t);
map.put(t, v + 1);
}
});
System.out.println(collect);
HashMap<Integer, AtomicInteger> collect2 = SimpleStream.of(List)
.collect(HashMap::new, (map, t) -> map.computeIfAbsent(t, k -> new AtomicInteger()).getAndIncrement());
System.out.println(collect2);
}
}
三. Stream API
filter过滤 Predicate
public class FilterTest {
public static void main(String[] args) {
Stream.of (
new Fruit(cname: "草莓", name: "Strawberry", category: "浆果", color: "红色"),
new Fruit(cname: "桑葚", name: "Mulberry", category: "浆果", color: "紫色"),
new Fruit(cname: "杨梅", name: "Waxberry", category: "浆果", color: "红色"),
new Fruit(cname: "核桃", name: "Walnut", category: "坚果", color: "棕色"),
new Fruit(cname: "花生", name: "Peanut", category: "坚果", color: "棕色"),
new Fruit(cname: "蓝莓", name: "Blueberry", category: "浆果", color: "蓝色")
)
.filter(f->f.category().equals("浆果")) // && f.color().equals("蓝色")
.filter(f->f.color().equals("蓝色"))
.forEach(System.out::println);
}
// Java 17新特性
record Fruit(String cname, String name, String category, String color) {
}
}
public class FilterTest {
public static void main(String[] args) {
Stream.of (
new Fruit(cname: "草莓", name: "Strawberry", category: "浆果", color: "红色"),
new Fruit(cname: "桑葚", name: "Mulberry", category: "浆果", color: "紫色"),
new Fruit(cname: "杨梅", name: "Waxberry", category: "浆果", color: "红色"),
new Fruit(cname: "核桃", name: "Walnut", category: "坚果", color: "棕色"),
new Fruit(cname: "花生", name: "Peanut", category: "坚果", color: "棕色"),
new Fruit(cname: "蓝莓", name: "Blueberry", category: "浆果", color: "蓝色")
)
.map(f->f.cname()+"酱") // Stream<String>
.forEach(System.out::println);
}
// Java 17新特性
record Fruit(String cname, String name, String category, String color) {
}
}
public class FilterTest {
public static void main(String[] args) {
Integer[][] array2D = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
};
Arrays.stream(array2D)
.flatMap(array -> Arrays.stream(array))
.forEach(System.out::println);
// Java 17新特性
record Fruit(String cname, String name, String category, String color) {
}
}
import java.util.List;
public class BuildStreamTest {
public static void main(String[] args) {
// 1. 从集合构建
Set.of(1, 2, 3).stream().forEach(System.out::println);
Map.of("a", 1, "b", 2).entrySet().stream().forEach(System.out::println);
int[] array = {1, 2, 3}
Arrays.stream(array).forEach(System.out::println);
// 3. 从对象构建
Stream.of(1, 2, 3, 4, 5).forEach(System.out::println);
}
}
public class ConcatSplitTest {
public static void main(String[] args) {
// 1. 合并
Stream<Integer> s1 = Stream.of(1, 2, 3);
Stream<Integer> s2 = Stream.of(4, 5);
Stream<Integer> concat = Stream.concat(s1, s2);
concat.forEach(System.out::println);
/*
2. 截取 - 直接给出截取位置
skip(long n) 跳过 n 个数据, 保留剩下的
limit(long n) 保留 n 个数据,剩下的不要
*/
// concat.skip(2).forEach(System.out::print);
concat.limit(2).forEach(System.out::print);
/**
takeWhile(Predicate p) 条件成立保留,一旦条件不成立,剩下的不要
dropWhile(Predicate p) 条件成立舍弃,一旦条件不成立,剩下的保留
*/
concat.takeWhile(x -> x < 3).forEach(System.out::print);
concat.dropWhile(x -> x < 3).forEach(System.out::print);
}
}
public class GenerateTest {
public static void main(String[] args) {
// 1. IntStream.range
IntStream.rang(1, 10).forEach(System.out::println);
IntStream.rangeClosed(1, 1).forEach(System.out::println);
// 2. IntStream.iterate 生成 1 3 5 7 9 ... 奇数序列 可以根据上一个元素值来生成当前元素
InStream.iterator(1, x -> x + 2).forEach(System.out::println);
InStream.iterator(1, x -> x <= 9, x -> x + 2).forEach(System.out::println);
// IntStream.generate
IntStream.generate(() -> ThreadLocalRandom.current().nextInt(100)).limit(5).forEach(System.out::println);
ThreadLocalRandom.current().ints(streamSize: 5, randomNumberOrigin: 0, randomNumber: 100).forEach(System.out::println);
}
}
import java.util.stream.IntStream;
public class FindTest {
public static void main(String[] args) {
IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);
// 找到第一个偶数
System.out.println(stream.filter(x -> (x & 1) == 0).findFirst().orElse(-1));
stream.filter(x -> (x & 1) == 0).findFirst().ifPresent((x)->System.out.println(x));
// 找到任意一个偶数
stream.filter(x -> (x & 1) == 0).findAny().ifPresent((x) -> System.out.println(x));
// 见名知意
System.out.println(stream.anyMatch(x -> (x&1) == 0));
System.out.println(stream.allMatch(x -> (x & 1)) == 0);
System.out.println(stream.noneMatch(x -> (x & 1)) == 0);
}
}
去重与排序
public class SortTest {
public static void main(String[] args) {
// 去重
IntStream.of(1, 2, 3, 1, 2, 3, 3, 4, 5)
.distince()
.forEach(System.out::println);
// 排序
Stream.of (
// 排序
new Hero(name: "令狐冲", strength: 90),
new Hero(name: "风清扬", strength: 98),
new Hero(name: "独孤求败", strength: 100),
new Hero(name: "方证", strength: 92),
new Hero(name: "东方不败", strength: 98),
new Hero(name: "冲虚", strength: 90),
new Hero(name: "向问天", strength: 88),
new Hero(name: "任我行", strength: 92),
new Hero(name: "不戒", strength: 88)
)
// 重要:简洁但可能存在溢出问题。
.sorted((a, b) -> a.strength() - b.strength()) // a.strenght < b.strength ? -1 : a.strength() == b.strength() ? 0 : 1
// .sorted((a, b) -> Integer.compare(a.strength(), b.strength()))
// .sorted((Comparator.comparingInt(h -> h.strength()))
.sorted(Comparator.comparingInt(Hero::strength).reverse().thenComparingInt(h->h.name.length()))
.forEach(System.out::println);
// Hero::strength <==> (h) -> h.strength();
record Hero(String name, int strength) {
}
}
}
reduce
import java.util.stream.Stream;
/*
简化:两两合并,只剩下一个
适合:最大值,最小值,求和,求个数...
.reduce((p, x) -> r) p 上次的合并结果,x 当前元素, r 本次合并结果
.reduce(init, (p, x) -> r)
.reduce(init, (p, x) -> r, (r1, r2) -> r)
*/
public class ReduceTest {
record Hero(String name, int strength) { ... }
public static void main(String[] args) {
Stream<Hero> result = Stream.of (
new Hero(name: "令狐冲", strength: 90),
new Hero(name: "风清扬", strength: 98),
new Hero(name: "独孤求败", strength: 100),
new Hero(name: "方证", strength: 92),
new Hero(name: "东方不败", strength: 98),
new Hero(name: "冲虚", strength: 90),
new Hero(name: "向问天", strength: 88),
new Hero(name: "任我行", strength: 92),
new Hero(name: "不戒", strength: 88)
);
// 1.求武力最高的 hero
Optional<Hero> result = stream.reduce((h1, h2) -> h1.strength() > h2.strength() ? h1 : h2)
Hero result = stream.reduce(new Hero("-", -1), (h1, h2) -> h1.strength() > h2.strength() ? h1 : h2);
System.out.println(result);
// 求高手总数
System.out.println(stream.map(h -> 1).reduce(0, (a, b) -> a + b));
System.out.println(stream.count());
stream.max(Comparator.comparingInt(Hero::strength));
stream.min(Comparator.comparingInt(Hero::strength));
stream.mapToInt(Hero::strength).sum());
stream.mapToInt(Hero::strength).average());
}
}
收集器
import java.util.stream.Stream;
public class C11CollectTest {
record Hero(String name, int strength) { ... }
/*
收集:将元素收集入容器
.collect(() -> c, (c, x) -> void, ?)
() -> c 创建容器 c
(c, x) -> void 将元素 x 加入 容器 c
*/
public static void main(String[] args) {
Stream<String> stream = Stream.of("令狐冲", "风清扬", "孤独求败", "方证", "东方不败","冲虚","向问天","任我行","不戒");
// 1.收集到 List
List<String> result = stream.collect(() -> new ArrayList<>(), (list, x) -> list.add(x), (a, b) -> { });
/*
ArrayList::new () -> new ArrayList()
ArrayList::add (list, x) -> list.add(x)
能等价就等价看自己的风格或要求
*/
// 缺点:不太方便调试
List<String> result = stream.collect(ArrayList::new, ArrayList::add, (a, b) -> { });
Set<String> result = stream.collect(LinkeeHashSet::new, Set::add, (a, b) -> { });
Map<String, Integer> result = stream.collect(HashMap::new, (map, x) -> map.put(x, 1), (a, b) -> { });
// 流空,不实现
stream.collect(StringBuilder::new, StringBuilder::append, (a, b) -> { });
stream.collect(() -> new StringJoiner(","), StringJoiner:add, (a, b) -> { });
}
}
import java.util.stream.Stream;
// 收集器 Collectors
public class C11CollectTest {
record Hero(String name, int strength) { ... }
/*
收集:将元素收集入容器
.collect(() -> c, (c, x) -> void, ?)
() -> c 创建容器 c
(c, x) -> void 将元素 x 加入 容器 c
*/
public static void main(String[] args) {
Stream<String> stream = Stream.of("令狐冲", "风清扬", "孤独求败", "方证", "东方不败","冲虚","向问天","任我行","不戒");
// 1.收集到 List
List<String> result = stream.collect(() -> new ArrayList<>(), (list, x) -> list.add(x), (a, b) -> { });
/*
ArrayList::new () -> new ArrayList()
ArrayList::add (list, x) -> list.add(x)
能等价就等价看自己的风格或要求
*/
// 缺点:不太方便调试
List<String> result = stream.collect(ArrayList::new, ArrayList::add, (a, b) -> { });
List<String> result = stream.collect(Collectors.toList());
Set<String> result = stream.collect(LinkeeHashSet::new, Set::add, (a, b) -> { });
Set<String> result = stream.collect(Collectors.toSet());
Map<String, Integer> result = stream.collect(HashMap::new, (map, x) -> map.put(x, 1), (a, b) -> { });
Map<String, Integer> result = stream.collect(Collectors.toMap(x -> x, x -> 1));
// 流空,不实现
stream.collect(StringBuilder::new, StringBuilder::append, (a, b) -> { });
stream.collect(Collectors.joining;
stream.collect(() -> new StringJoiner(","), StringJoiner:add, (a, b) -> { });
stream.collect(Collectors.joining(","));
/*
3:new ArrayList(["令狐冲", “风清扬", “向问天",“任我行"])
4:new ArrayList(["独孤求败","东方不败"])
2: new ArrayList(["方证",“冲虚",“不戒"])
*/
Map<Integer, List<String>> result = stream.collect(Collectors.groupingBy(x -> x.length(), Collectors.toList()));
for (Map.Entry<Integer, List<String>> e : result.entrySet()) {
System.out.println(e);
}
/**
1. mapping(x->y, dc) 需求:根据名字长度分组,分组后组内只保留他们的武力值
new Hero("令狐冲", 90) -> 90
dc 下游收集器 down collector
*/
Map<Integer, List<Integer>> collect = stream.collect (
groupingBy(h -> h.name().length(), mapping(h -> h.strength(), toList())));
for (Map.Entry<Integer, List<Integer>> e : collect.entrySet()) {
System.out.println(e);
}
/*
* 2. filtering(x -> boolean, dc) 需求:根据名字长度分组,分组后组内过滤掉武力小于 90 的
*/
// 在分组收集的过程中,执行过滤
Map<Integer, List<Hero>> collect1 = stream.collect (
groupingBy(h -> h.name().length(), filtering(h -> h.strength() >= 90, toList()));
)
// 先过滤,再来分组收集
Map<Integer, List<Hero>> collect1 = stream.filter(h -> h.strength() >= 90)
.collect(groupingBy(h -> h.name().length(), toList()));
for (Map.Entry<Integer, List<Hero>> e : collect1.entrySet()) {
System.out.println(e);
}
/**
* 3. flatMapping(x -> substream, dc) 需求:根据名字长度分组,分组后组内保留人名,并且人名切分成单个字符
*/
// Character::toString (x) -> x.toString();
"令狐冲".chars().mapToObj(Character.toString.forEach(System.out::println);
stream.collect(groupingBy(h -> h.name().length(), flatMapping(h->h.name().chars().mapToObj(Character::toString), toList())));
for (Map.Entry<Integer, List<String>> e : collect.entrySet()) {
System.out.println(e);
}
/*
* 4. counting() 需求:根据名字长度分组,分组后求每组个数
*/
Map<Integer, Long> collect = stream.collect(groupingBy(h -> h.name().length(), count()));
for (Map.Entry<Integer, Long> e : collect.entrySet()) {
System.out.println(e);
}
/*
* minBy((a, b) -> int) 需求:根据名字长度分组,分组后求每组武功最低的人
* maxBy((a, b) -> int) 需求:根据名字长度分组,分组后求每组武功最高的人
*/
stream.collect(groupingBy(h -> h.name().length(), maxBy(Comparator.comparingInt(Hero::strength))));
/*
* 7. summingInt(x -> int) 需求:根据名字长度分组,分组后求每组武力和
* 8. averagingDouble(x -> double) 需求:根据名字长度分组,分组后求每组武力平均值
*
* stream.collect(groupingBy(h -> h.name().length(), averagingDouble(h -> h.strength())));
*/
for (Map.Entry<Integer, Optional<Hero>> e : collect.entrySet()) {
System.out.println(e);
}
/*
* 9. reducing(init, (p, x) -> r)
*/
stream.collect(groupingBy(h -> h.name().length(), mapping(h -> h.strength(), reducing(0, (p, x) -> p + x))));
}
}
基本流
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.uyil.stream.LongStream;
import java.util.stream.Stream;
public class C14Effective {
/*
三种基本流
*/
public static void main(String[] args) {
IntStream a = IntStream.of(97, 98, 99);
LongStream b = LongStream.of(1L, 2L, 3L);
DoubleStream c = DoubleStream.of(1.0, 2.0, 3.0);
Stream<Integer> d = Stream.of(1, 2, 3);
a.mapToObj(Character::toString).forEach(System.out::println);
IntSummaryStatistics stat = a.summaryStatistics();
System.out.println(stat.getSum());
System.out.println(stat.getCount());
System.out.println(stat.getMax());
System.out.println(stat.getMin());
System.out.println(stat.getAverage());
Stream<Hero> stream = Stream.of(
new Hero("令狐葱", 90),
new Hero("风清扬", 98)
);
stream.mapToInt(Hero::strength).forEach(System.out::println);
}
}
流的特性
import java.util.stream.Stream;
public class C15Summary {
public static void main(String[] args) {
/**
* 掌握 Stream 流的特性
* 1. 一次使用
* 2. 两类操作(中间操作 lazy 懒惰, 终结操作 eager 迫切)
*/
Stream<Integer> s1 = Stream.of(1, 2, 3, 4, 5);
s1
.map(x -> x + 1)
.filter(x -> x <= 5)
.forEach(x -> System.out::println);
}
}
stream 并行
import static java.util.stream.Collectors.toList;
// 并行流
public class C16Parallel {
public static void main(String[] args) {
/* ... */
List<Integer> collect = Stream.of(1, 2, 3, 4)
.parallel()
.collect(Collector.of (
() -> new ArrayList(), // 如何创建容器
(list, x) -> list.add(x), // 如何向容器添加数据
(list1, list2) -> {
list1.addAll(list2);
return list1;
}, // 如何合并两个容器的数据
list -> list // 收尾
// 特性:并发,是否需要收尾,是否要保证收集顺序 (默认)容器不支持并发,需要收尾,要保证收集顺序
));
System.out.println(collect);
}
private static String simple() { }
}
import static java.util.stream.Collectors.toList;
// 并行流
public class C16Parallel {
public static void main(String[] args) {
/* ... */
List<Integer> collect = Stream.of(1, 2, 3, 4)
.parallel()
.collect(Collertor.of)(
() -> {
System.out.printf("%-12s %s%n", simple(), "create"); // 1.如何创建容器
return new ArrayList<Integer>();
},
(list, x) -> {
List<Integer> old = new ArrayList<>(list);
list.add(x);
System.out.printf("%-12s %s.add(%d)=>%s%n", simple(), old, x, list);
}, // 2. 如何向容器添加数据
(list1, list2) -> {
List<Integer> old = new ArrayList<>(list1);
list1.addAll(list2);
System.out.println("%-12s %s.add(%s)=>%s%n", simple(), lod, list2, list3);
return list1;
} // 3.如何合并两个容器的数据
list -> {
System.out.printf("%-12s finish: %s=>%s%n", simple(), list, list);
return list;
} // 4.收尾
// 5. 特性:容器不支持并发,需要收尾,要保证收集顺序
)
System.out.println(e);
}
private static String simple() { }
}
public class C16Parallel {
public static void main(String[] args) {
/*
* 1. 数据量问题:数据量大时才建议用并行流
* 2. 线程会无限增加吗:跟 cpu 能处理的线程数相关
* 3. 收尾的意义: 转不可变集合,StringBuilder 转 String
* 4. 是否线程安全: 不会有线程安全问题
* 5. 特性
* 是否需要收尾(默认收尾),
是否需要保证顺序(默认保证)
容器是否支持并发(默认不支持)
到达选择哪一种?
A. Characteristics.CONCURRENT + Characteristics.UNORDERED + 线程安全容器
B. 默认 + 线程不安全容器
*/
List<Integer> collect = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
.parallel()
.collect(Collertor.of(
() -> {
System.out.printf("%-12s %s%n", simple(), "create"); // 1.如何创建容器
return new ArrayList<Integer>();
},
(list, x) -> {
List<Integer> old = new ArrayList<>(list);
list.add(x);
System.out.printf("%-12s %s.add(%d)=>%s%n", simple(), old, x, list);
}, // 2. 如何向容器添加数据
(list1, list2) -> {
List<Integer> old = new ArrayList<>(list1);
list1.addAll(list2);
System.out.println("%-12s %s.add(%s)=>%s%n", simple(), lod, list2, list3);
return list1;
} // 3.如何合并两个容器的数据
list -> {
System.out.printf("%-12s finish: %s=>%s%n", simple(), list, list);
return Collections.unmodifiableList(list);
} // 4.收尾
// 5. 特性:容器不支持并发,需要收尾,要保证收集顺序
, Collector.Characteristics.IDENTITY_FINISH // 不需要收尾
,Collector.Characteristics.UNORDERED // 不需要保证顺序
, Collector.Characteristics.CONCURRENT // 容器需要支持并发
)
System.out.println(e);
collect.add(100);
}
private static String simple() { }
Stream 流的性能
// 性能: 求和 JMH
public class T01Sum {
@State(Scope.Benchmark)
public static class MyState { ... }
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int primitive(MyState state) {
int sum = 0;
for (int number : state.numbers) {
sum += number;
}
return sum;
}
@Benchmark
@BenchmarkMode(Mode.AveragetTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int boxed(MyState state) {
int sum = 0;
for (Integer i : state.numberList) {
sum += i;
}
return sum;
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int stream(MyState state) {
return state.numberList.stream().reduce(0, (a, b) -> a + b);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int intStream(MyState state) {
return IntStream.of(state.numbers).sum();
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(TO1Sum.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
pubilc class T02Parallel {
static final int n = 1000000;
@State(Scope.Benchmark)
pubilc static class MyState {
int[] numbers = new int[n];
{
for (int i = 0; i < n; i++) {
numbers[i] = ThreadLocalRandom.current().nextInt(10000000);
}
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int primitive(MyState state) {
int max = 0;
for (int number : state.numbers) {
if (number > max) {
max = number;
}
}
return max;
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int sequence(MyState state) {
return IntStream.of(state.numbers).max().orElse(0);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int parallel(MyState state) {
return IntStram.of(state.number).parallel().max().orElse(0);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int custom(Mystate state) throws ExecutionException, InterruptedException {
int[] numbers = state.numbers;
int step = n / 10;
ArrayList<Future<Integer>> result = new ArrayList<>();
try (ExecutorService service = Executors.newVirtualThreadPerTaskExecutor()) {
for (int j = 0; j < n; j += step) {
int k = j;
result.add(service.submit(() -> {
int max = 0;
for (int i = k; i < k + step; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
return max;
}));
}
System.out.println(result.size());
int max = 0;
for (Future<Integer> future : result) {
if (future.get() > max) {
max = future.get();
}
}
return max;
}
}
}
import static java.util.stream.Collectors.*;
public class T03Concurrent {
static final int n = 1000000;
@State(Scope.Benchmark)
public static class MyState {
int[] numbers = new int[n];
{
for (int i = 0; i < n; i++) {
numbers[i] = ThreadLocalRandom().current().nextInt(n / 10);
}
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public Map<Integer, Integer> loop1(MyState state) {
Map<Integer, Integer> map = new HashMap<>();
for (int number : state.numbers) {
map.merge(number, 1, Integer::sum);
}
return map;
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public Map<Integer, Integer> loop1(MyState state) {
Map<Integer, Integer> map = new HashMap<>();
for (int number : state.numbers) {
map.computeIfAbsent(number, k -> new AtomicInteger()).getAndIncrement();
}
return map;
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public Map<Integer, Long> sequence(MyState state) {
return Arrays.stream(state.numbers).boxed()
.collect(groupingBy(Function.identity(), counting()));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public Map<Integer, Long> parallelNoConcurrent(MyState state) {
return Arrays.stream(state.numbers).boxed()
.parallel()
.collect(groupingBy(Function.identity(), counting()));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public ConcurrentMap<Integer, Long> parallelConcurrent(MyState state) {
return Arrays.stream(state.numbers).boxed()
.parallel()
.collect(groupingByConcurrent(Function.identity(), counting()));
}
public static void main(String[] args) throws RunnerException, ExecutionException, InterruptedException {
}
}
四.实际应用统计、异步、框架、并行、事件
统计
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(Path.of("./data.txt"))) {
lines.skip(1).limit(5).forEach(line->System.out.println(line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
每月的销售量
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(Path.of("./data.txt"))) {
long start = System.currentTimeMillis();
Map<YearMonth, Long> collect = lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> YearMonth).from(formatter.parse(array[TIME]), TreeMap::new, counting()));
System.out.println("花费" + (System.currentTimeMillis() - start));
for (Map.Entry<YearMoth, Long> e : collect.entrySet()) {
System.out.println(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
统计销量最高的月份
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(Path.of("./data.txt"))) {
lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> YearMonth.from(formatter.parse(array[TIME])), counting()))
.entrySet().stream()
// .max(Comparator.comparingLong(e -> e.getValue()));
.max(Map.Entry.comparingByValue())
.ifPresent(x -> System.out.println(x));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
销量最高的商品
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case3();
}
private static void case3() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
lines.skip(1)
.map(line->line.split(","))
.collect(groupingBy(array->array[PRODUCT_ID], counting()))
.entrySet().stream()
.max(Map.Entry.comparingByValue())
.ifPresent(System.out::println);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
下单最多的前10用户
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case4();
}
private static void case4() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
lines.skip(1)
.map(line -> line.split(",")
.collect(groupingBy(array -> array[USER_ID], counting));
for (Map.Entry<String, Long> e : collect.entrySet()) {
System.out.println(e);
}
collect.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(10)
.forEach(System.out::println);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
最小堆
static class MyQueue<E> extends PriorityQueue<E> {
private int max;
public MyQueue(Comparator<? super E> comparator, int max) {
super(comparator);
this.max = max;
}
@Override
public boolean offer(E e) {
boolean r = supper.offer(e);
if (this.size() > max) {
this.poll();
}
return r;
}
}
private static void case4() {
try (Stream<String> lines = Files.lines(Path.of("./data.txt"))) {
Map<String, Long> collect = lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> array[USER_ID], counting()));
// 小顶推
MyQueue<Map.Entry<String, Long>> map = collect.entrySet().stream()
.collect (
() -> new MyQueue<Map.Entry<String, Long>(Map.Entry.comparingByValue())
(queue, x) -> queue.offer(x),
(q1, q2) -> q1.addAll(q2)
);
while(!queue.isEmpty()) {
System.out.println(queue.poll());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
每个地区下单最多的用户
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case5();
}
private static void case5() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
Map<String, Map<String, Long>> collect = lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> array[USER_GEGION], groupingBy(array -> array[USER_ID], counting())));
collect.entrySet().stream.map(e -> Map.entry(
e.getKey(),
e.getValue().entrySet().stream()
.max(Map.Entry.comparingByValue())
))
.forEach(System.out::println);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
每个地区下单最多的前3用户
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case5();
}
private static void case5() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
Map<String, Map<String, Long>> collect = lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> array[USER_GEGION], groupingBy(array -> array[USER_ID], counting())));
collect.entrySet().stream.map(e -> Map.entry(
e.getKey(),
// e.getValue().entrySet().stream()
// .sorted(Map.Entry.comparingByValue().reverse())
// .limit(3)
// .collect(toList())
e.getValue().entrySet().stream()
.collect (
() -> new MyQueue<Map.Entry<String, Long>> (Map.Entry.comparingByValue(), 3)
MyQueue::offer
MyQueue::addAll
)
))
.forEach(System.out::println);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
按一级类别统计销量
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case6();
}
static String firstCategory(String[] array) {
String c = array[CATEGORY_CODE];
int idx = c.indexOf(".");
return c.substring(0, idx);
}
private static void case6() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
Map<String, Long> collect = lines.skip(1)
.map(line -> line.split(","))
.filter(array -> !array[CATEGORY_CODE].isEmpty())
.collect(groupingBy(TestData::firstCategory, TreeMap::new, counting()));
for (Map.Entry<String, Long> e : collect.entrySet()) {
System.out.println(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
按区间统计销量
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case7();
}
static String priceRange(Double price) {
if (price < 100) {
return "[0, 100)";
} else if (price >= 100 && price < 500) {
return "[100, 500)"
} else if (price >= 500 && price < 1000) {
return "[500, 1000)";
} else {
return "[1000, 无穷)";
}
}
private static void case6() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
lines.skip(1)
.map(line -> line.split(","))
.map(array->Double.valueOf(array[PRICE]))
.collect(groupingBy(TestData::priceRange, counting()));
// 打印集合 略
} catch (IOException e) {
throw new RuntimeException(e);
}
}
不同年龄段女性下不同类别订单
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
public static void main(String[] args) {
case8();
}
static String ageRange(Double price) {
int age = Double.valueOf(array[USER_AGE]).intValue();
if (age < 18) {
return "[0, 18)";
} else if (age < 30) {
return "[18, 30)";
} else if (age < 50) {
return "[30, 50)";
} else {
return "[50, 无穷)"
}
}
private static void case8() {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
lines.skip(1)
.map(line -> line.split(","))
.filter(array->array[USER_SEX].equals("女"))
.filter(array-> array[CATEGORY_CODE].isEmpty())
.collect(groupingBy(TestData::ageRange,
groupingBy(TestData::firstCategory, TreeMap::new, counting())));
for (Map.Entry<String, Map<String, Long>> e1 : map.entrySet()) {
for (Map.Entry<String, Long> e2 : e1.getValue().entrySet()) {
System.out.println("%-12s%-15s%d%n", e1.getKey(), e2.getKey(), e2.getValue());
}
}
// 打印集合 略
} catch (IOException e) {
throw new RuntimeException(e);
}
}
异步处理
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
static Logger logger = LoggerFactory.getLogger("Test");
// 1. 显式使用了线程池
// 2. 函数对象嵌套使用,可读行差
public static void main(String[] args) {
logger.info("开始统");
// monthlySalesReport();
new Thread()->monthlySalesReport().start(); // 异步代码调用
logger.info("执行其他操作");
/*
目标:将处理结果的逻辑放在 monthlySalesReport 之外
做法1:将结果作为方法的返回值返回
做法2:将处理结果的逻辑作为函数对象传递给方法
*/
try (ExcutorService service = Executors.newFixedThreadPool(3)) {
logger.info("开始统计");
service.submit(()-> {
monthlySalesReport((map) -> {
logger.info(e.toString());
});
});
logger.info("执行其他操作");
}
}
private static void monthlySalesReport(Counsumer<Map<YearMonth, Long>> consumer) {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
Map<YearMonth, Long> map = lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> YearMonth.from(formatter.parse(array[TIME], TreeMap::new, counting())));
return collect;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
异步优化
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletebleFuture;
public class C03CompletableFutureTest {
static Logger logger = loggerFactory.getLogger("Test");
public static void main(String[] args) {
// 1. 异步执行
CompletableFuture.runAsync() // 在任务不需要返回结果时
CompletableFuture.supplyAsync() // 在任务需要处理结果时
CompletableFuture.runAsync(() -> logger.info("异步操作1"));
CompletableFuture.supplyAsync(() -> {
logger.info("异步操作2");
return "结果";
}).thenApply(r -> r + "转换后")
.thenAccept(r -> logger.info(r));
System.in.read(); // 不让主线程立刻结束
// 2.处理异步任务的结果
/*
thenApply(Function)
thenApplyAsync
thenAccept(Consumer)
thenAcceptAsunc(Consumer)
*/
}
}
static final int INDEX = 0;
static final int TIME = 1;
static final int ORDER_ID = 2;
static final int PRODUCT_ID = 3;
static final int CATEGORY_ID = 4;
static final int CATEGORY_CODE = 5;
static final int BRAND = 6;
static final PRICE = 7;
static final int USER_ID = 8;
static final int USER_AGE = 9;
static final int USER_SEX = 10;
static final int USER_REGION = 11;
static final int DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM--dd HH:mm:ss z");
static Logger logger = LoggerFactory.getLogger("Test");
// 1. 显式使用了线程池
// 2. 函数对象嵌套使用,可读行差
public static void main(String[] args) {
CompletableFuture
.supplyAsync(() -> monthlySalesReport())
.thenAccept(map -> {
for (Map.Entry<YearMonth, Long> e : map.entrySet()) {
logger.info(e.toString());
}
});
System.in.read();
try (ExcutorService service = Executors.newFixedThreadPool(3)) {
logger.info("开始统计");
CompletableFuture
.supplyAsync(() -> monthlySalesReport)
.thenAccept(map -> {
for (Map.Entry<YearMonth, Long> e : map.entrySet()) {
logger.info(e. toString());
}
});
logger.info("执行其他操作");
System.in.read();
}
}
private static void monthlySalesReport(Counsumer<Map<YearMonth, Long>> consumer) {
try (Stream<String> lines = Files.lines(Paths.get("./data.txt")) {
Map<YearMonth, Long> map = lines.skip(1)
.map(line -> line.split(","))
.collect(groupingBy(array -> YearMonth.from(formatter.parse(array[TIME], TreeMap::new, counting())));
return collect;
} catch (IOException e) {
throw new RuntimeException(e);
}
}