map
若map里key对应的value为空,会将第二个参数的返回值存入并返回,不为空就不放入map
// java8之前。从map中根据key获取value操作可能会有下面的操作
Object key = map.get("key");
if (key == null) {
key = new Object();
map.put("key", key);
}
// java8之后。上面的操作可以简化为一行,若key对应的value为空,会将第二个参数的返回值存入并返回
Object key2 = map.computeIfAbsent("key", k -> new Object());
List和Map转换
List<Person> javaProgrammers = new ArrayList<Person>() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
add(new Person("Elsdon", 2000));
add(new Person("Tamsen", 1500));
add(new Person("Floyd", 1800));
add(new Person("Sindy", 1600));
add(new Person("Vere", 1200));
add(new Person("Maude", 1900));
add(new Person("Shawn", 2300));
add(new Person("Jayden", 1700));
add(new Person("Palmer", 2000));
add(new Person("Addison", 1300));
}
};
Map<String,Integer> map =
javaProgrammers.stream().collect(
Collectors.toMap(Person::getName, Person::getAge,
(name, age) -> age, LinkedHashMap::new));
// Map<String,Integer> map1 = javaProgrammers.stream().collect(Collectors.
// toMap(Person::getName, Person::getAge, (name, age) -> age));
System.out.println(map);
运行结果
{Elsdon=2000, Tamsen=1500, Floyd=1800, Sindy=1600, Vere=1200, Maude=1900, Shawn=2300, Jayden=1700, Palmer=2000, Addison=1300}
Map<String, Person> map =
javaProgrammers.stream().collect(
Collectors.toMap(Person::getName, e -> e));
Map<String, Person> map1 =
javaProgrammers.stream().collect(
Collectors.toMap(Person::getName, Function.identity()));
运行结果 都是
{Shawn=Person [name=Shawn, age=2300], Elsdon=Person [name=Elsdon, age=2000], Palmer=Person [name=Palmer, age=2000], Addison=Person [name=Addison, age=1300], Maude=Person [name=Maude, age=1900], Floyd=Person [name=Floyd, age=1800], Vere=Person [name=Vere, age=1200], Jayden=Person [name=Jayden, age=1700], Tamsen=Person [name=Tamsen, age=1500], Sindy=Person [name=Sindy, age=1600]}
但是上面的方法当key重复时会异常
可以使用下面的方法来解决
Map<String, Person> map = javaProgrammers.stream().collect(Collectors.toMap(
Person::getName, Function.identity(), (key1, key2) -> key2));
Map<String, Person> map1 = javaProgrammers.stream().collect(Collectors.toMap(
Person::getName, Function.identity(), (key1, key2) -> key2, LinkedHashMap::new));
运行结果 都是
{Shawn=Person [name=Shawn, age=2300], Elsdon=Person [name=Elsdon, age=1500], Palmer=Person [name=Palmer, age=2000], Addison=Person [name=Addison, age=1300], Maude=Person [name=Maude, age=1900], Floyd=Person [name=Floyd, age=1800], Vere=Person [name=Vere, age=1200], Jayden=Person [name=Jayden, age=1700], Sindy=Person [name=Sindy, age=1600]}
{Elsdon=Person [name=Elsdon, age=1500], Floyd=Person [name=Floyd, age=1800], Sindy=Person [name=Sindy, age=1600], Vere=Person [name=Vere, age=1200], Maude=Person [name=Maude, age=1900], Shawn=Person [name=Shawn, age=2300], Jayden=Person [name=Jayden, age=1700], Palmer=Person [name=Palmer, age=2000], Addison=Person [name=Addison, age=1300]}
第一个算式的含义:如果key一样,就只保留key最后出现时的对象
第一个算式的含义:如果key一样,就只保留key第一次出现时的对象
2. 聚合函数
public static void main(String[] args) {
List<Person> javaProgrammers = new ArrayList<Person>() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
add(new Person("Elsdon", 2000));
add(new Person("Elsdon", 1500));
add(new Person("Floyd", 1800));
add(new Person("Sindy", 1600));
add(new Person("Vere", 1200));
add(new Person("Maude", 1900));
add(new Person("Shawn", 2300));
add(new Person("Jayden", 1700));
add(new Person("Palmer", 2000));
add(new Person("Addison", 1300));
}
};
System.out.println(javaProgrammers.stream().collect(Collectors.groupingBy(Person::getName)));
System.out.println(javaProgrammers.stream().collect(Collectors.counting()));
System.out.println(javaProgrammers.stream().collect(Collectors.averagingInt(e -> e.getAge())));
System.out.println(javaProgrammers.stream().collect(Collectors.summingInt(e -> e.getAge())));
System.out.println(javaProgrammers.stream().collect(Collectors.minBy((e1, e2) -> e1.getAge() - e2.getAge())).get());
System.out.println(javaProgrammers.stream().collect(Collectors.maxBy((e1, e2) -> e1.getAge() - e2.getAge())).get());
System.out.println(javaProgrammers.stream().mapToInt(Person::getAge).max().orElse(-1));
System.out.println(javaProgrammers.stream().collect(Collectors.maxBy((e1, e2) -> e1.getAge() - e2.getAge())).get());
System.out.println(javaProgrammers.stream().collect(Collectors.summarizingInt(e -> e.getAge())));
}
运行结果
{Shawn=[Person [name=Shawn, age=2300]], Elsdon=[Person [name=Elsdon, age=2000], Person [name=Elsdon, age=1500]], Palmer=[Person [name=Palmer, age=2000]], Addison=[Person [name=Addison, age=1300]], Maude=[Person [name=Maude, age=1900]], Floyd=[Person [name=Floyd, age=1800]], Vere=[Person [name=Vere, age=1200]], Jayden=[Person [name=Jayden, age=1700]], Sindy=[Person [name=Sindy, age=1600]]}
10
1730.0
17300
Person [name=Vere, age=1200]
Person [name=Shawn, age=2300]
2300
Person [name=Shawn, age=2300]
IntSummaryStatistics{count=10, sum=17300, min=1200, average=1730.000000, max=2300}
flatMap
List<Person> list = new ArrayList<Person>() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
add(new Person("andy|koni", 2000));
add(new Person("Elsdon", 1500));
add(new Person("Floyd", 1800));
add(new Person("Sindy", 1600));
add(new Person("Vere", 1200));
add(new Person("Maude", 1900));
add(new Person("Shawn", 2300));
add(new Person("Jayden", 1700));
add(new Person("Palmer", 2000));
add(new Person("Addison", 1300));
}
};
List<String> nameq = list.stream().map(x -> Arrays.asList((x.getName().split("\\|")))).flatMap(x -> x.stream()).collect(Collectors.toList());
System.out.println(nameq);
}
运行结果
[andy, koni, Elsdon, Floyd, Sindy, Vere, Maude, Shawn, Jayden, Palmer, Addison]
重写Person
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
public Person() {
}
private List<String> names = new ArrayList<>();
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
@Override
public String toString() {
return "Person [names=" + names + ", name=" + name + ", age=" + age + "]";
}
}
public static void main(String[] args) {
List<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.get(0).getNames().add("DogA5");
list.get(1).getNames().add("DogB12");
list.get(2).getNames().add("DogA9");
list.get(3).getNames().add("DogC11");
list.get(4).getNames().add("DogD10");
list.get(3).getNames().add("dogc11");
list.get(4).getNames().add("dogd10");
List<String> nameq = list.stream().map(x -> x.getNames()).flatMap(x -> x.stream()).collect(Collectors.toList());
System.out.println(nameq);
}
运行结果
[DogA5, DogB12, DogA9, DogC11, dogc11, DogD10, dogd10]
::
下面表达等价
list.stream().map(e -> e.getName()).collect(Collectors.toList());
list.stream().map(JsonField::getName).collect(Collectors.toList());
e的类型是JsonField,所以可以写成第二种表达式
Function 是要接受一个参数,返回一个参数
比如 我们写个文字串子转数字的函数
原来的写法是
public static <T extends Number> T string2Number(String value , Class<T> clazz) {
if (Objects.isNull(value) || value.isEmpty() ) {
return null;
}
if (clazz == BigDecimal.class) {
return clazz.cast(new BigDecimal(value));
} else if (clazz == Long.class) {
return clazz.cast(Long.valueOf(value));
} else if (clazz == Long.class) {
return clazz.cast(Integer.valueOf(value));
} else if (clazz == Float.class) {
return clazz.cast(Float.valueOf(value));
}
return null;
}
可以改写代码
public static <T extends Number> T string2Number(Function<String, T> function, String numberValue) {
if (Objects.isNull(numberValue) || numberValue.isEmpty() ) {
return null;
}
return function.apply(numberValue);
}
string2Number(Long::valueOf, "2") // ①
string2Number(BigDecimal::new, "2") // ②
string2Number(value -> Long.valueOf(value), "2"); // ③
①和③ 是一样的,③的意思是,传入"2",然后调用 string2Number 函数,当执行到function.apply(numberValue);时,numberValue变成③的value,执行 Long.valueOf(value);
string2Number的Function<String, T> function,其中String是输入参数numberValue的类型,T是function.apply返回的类型
如果没有返回值只有参数的时,用Consumer
如果没有参数只有返回值时,用Supplier
传参返回布尔型用Predicate
前个对象和后个对象比较
public <T> Predicate<T> nextEquals(Function<? super T, Object> keyExtractor) {
Deque<T> deque = new ArrayDeque<>();
return object -> (!deque.isEmpty() && (keyExtractor.apply(deque.pop()).equals(keyExtractor.apply(object)) && deque.add(object)))
|| !deque.add(object);
}
Employee e1 = new Employee("23", 25, 3000, 9922001);
Employee e2 = new Employee("21", 22, 2000, 5924001);
Employee e3 = new Employee("John1", 35, 4000, 3924401);
Employee e4 = new Employee("John2", 55, 3000, 9922001);
Employee e5 = new Employee("John1", 12, 2000, 5924001);
List<Employee> employees = new ArrayList<>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
employees.add(e4);
employees.add(e5);
// 要求任意一个前后的Employee 的 name 相同
System.out.println(employees.stream().anyMatch(nextEquals(Employee::getName)));
先做个stack用来存放当前在对象,
当第一条进来的时候(我们不知道后面下一个的内容,所以要求不比较,并且以不相等作为结果,所以直接返回false):
deque 是空的
通过!deque.isEmpty() 来返回false。但是这时还要把当前对象放入stackdeque 。我们就用|| !deque.add(object)来实现。因为deque.add永远返回true.当执行 !deque.add就是永远返回false,这样就做到 一句代码中不影响结果,并把当前在记录放入stack中。
当后面几条进来时
就会运行到 (keyExtractor.apply(deque.pop()).equals(keyExtractor.apply(object))
stack.pop() 是前面一条记录,object是当前那条记录。来做完比较。
最后的 && deque.add(object) 是在前面返回true在的时候不影响结果,来把当前在记录放入deque中
distinct
distinct通过传进去的字段
public <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Set<Object> distinctSet = new HashSet<>();
// T 是 下面的 object, Object 是 keyExtractor.apply(object))的返回值
return object -> distinctSet.add(keyExtractor.apply(object));
}
List<Employee> employeeList = employees.stream()
.filter(distinctByKey(Employee::getName))
.collect(Collectors.toList());
指定长度的stream
IntStream.range(0, 10).boxed()
.collect(Collectors.toList())
.forEach(System.out::print);
GROUP BY后 求最大,最小
Map<String, User> stu1 = list.stream()
.collect(Collectors.toMap(User::getClassId, Function.identity(),
BinaryOperator.minBy(Comparator.comparing(User::getAge))));
Map<String, Optional<User>> stu2 = list.stream()
.collect(Collectors.groupingBy(User::getClassId,
Collectors.minBy(Comparator.comparingInt(User::getAge))));
索引
// 创建一个AtomicInteger
AtomicInteger index = new AtomicInteger(0);
List.map(str -> index.getAndIncrement())
// 打印元素和索引
.forEach(System.out::println);
結果:
0
1
2
addAndGet()- 以原子方式将给定值添加到当前值,并在添加后返回新值。
getAndAdd() - 以原子方式将给定值添加到当前值并返回旧值。
incrementAndGet()- 以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。
getAndIncrement() - 以原子方式递增当前值并返回旧值。它相当于++ i操作。
decrementAndGet()- 原子地将当前值减1并在减量后返回新值。它等同于i-操作。
getAndDecrement() - 以原子方式递减当前值并返回旧值。它相当于-i操作。