https://github.com/itwanger/toBeBetterJavaer/blob/master/docs/collection/gailan.md
Collection
:一种装数据的容器,可以存储多个数据
所有单列接口的顶层接口,定义了所有单列集合的共有方法
任意的单列集合都可以使用Collection接口中的方法
NavigableMap
可以按升序或降序键顺序访问和遍历
CopyOnWrite ArrayList
读写分离:读时共享、写时复制(原本的array)更新(且为独占式的加锁
-
每个CopyOnWriteList对象里面有一个array数组来存放具体元素
-
使用ReentrantLock独占锁来保证只有写线程对array副本进行更新。
-
CopyOnWriteArrayList在遍历的使用不会抛出ConcurrentModificationException异常,并且遍历的时候就不用额外加锁
Collections.SynchronizedList
同步代码块实现,迭代器没有加锁
CopyOnWrite ArraySet
其实CopyOnWriteSet底层包含一个CopyOnWriteList,几乎所有操作都是借助CopyOnWriteList,就像HashSet包含HashMap
-
它最适合于具有以下特征的应用程序:Set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
-
它是线程安全的。
-
因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
-
迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。
-
使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。
Collections.SynchronizedList
这几个方法没有加锁
itearator(),spliterator(),stream(),parallelStream()
ConcurrentHashMap
在内部采用了一个叫做Segment的结构,一个Segment其实就是一个类Hash Table的结构,Segment内部维护了一个链表数组
Collections.SynchronizedMap
int size();
获取集合尺寸
boolean isEmpty();
判断集合是否为空
boolean contains(Object o);
判断集合是否包含指定的对象
Object[] toArray();
集合转换数组
boolean add(E e);
追加元素
boolean remove(Object o);
删除指定的元素
void clear();
清空集合
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
添加集合
Collection<String> list =new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
System.out.println(list);
ArrayList<String> ls =new ArrayList<>();
ls.add("dd");
ls.add("fsf");
//集合添加集合
list.addAll(ls);
System.out.println(list);
//判断集合是否为空
System.out.println(list.isEmpty());
//判断集合是否包含
System.out.println(list.contains("ccc"));
//集合转数组
Object[] obj = list.toArray();
for (int i = 0; i < obj.length; i++) {
System.out.print(obj[i]+"\t");
}
System.out.println();
//清空集合
list.clear();
System.out.println(list);
数组:程序运行后,数组的长度固定 ,添加或者减少元素变得困难
存储的同一类型 的元素,可以存储基本类型值
集合:长度可变
存储的都是对象类型 ,而且对象类型可以不一致 ,当开发中存储对象比较多的时候,推荐使用集合
继承与Collection接口,存放的是可以重复的元素
List集合 : 底层采用的数据结构数组
-
存入的数据都是有序 ,可以重复的元素 ,有序--->存储的顺序和取出来顺序是一致的
-
有索引的 ,包含一些带索引的方法
static <E> List<E> of(E e1)
: 生成一个不可变的集合
public class Demo {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("hello");
list.add("hello");
list.add("bbb");
list.add("aaa");
System.out.println(list);
//添加元素
list.add(1,"ccc");
System.out.println(list);
//删除元素
list.remove(0);
list.remove("aaa");
System.out.println(list);
//设置元素
list.set(0,"aaa");
System.out.println(list);
//遍历元素
Iterator<String> iterator=list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
for (String s : list) {
System.out.println(s);
}
//新特性:不变的集合
List<String> li = List.of("aaa", "bbb", "ccc", "ddd");
System.out.println(li);
li.add("sss"); // UnsupportedOperationException
}
}
public class Demo {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("hello");
list.add("hello");
list.add("bbb");
list.add("aaa");
System.out.println(list);
//添加元素
list.add(1,"ccc");
System.out.println(list);
//删除元素
list.remove(0);
list.remove("aaa");
System.out.println(list);
//设置元素
list.set(0,"aaa");
System.out.println(list);
//遍历元素
Iterator<String> iterator=list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
for (String s : list) {
System.out.println(s);
}
//新特性:不变的集合
List<String> li = List.of("aaa", "bbb", "ccc", "ddd");
System.out.println(li);
li.add("sss"); // UnsupportedOperationException
}
}
-
排列有序,可重复
-
底层使用数组
-
速度快,增删慢
get(),set()
-
线程不安全
-
当容量不够的时候自动扩容 比例:
当前容量 * 1.5
ArrayList<E>
泛型 ,通过集合后续给定的类型,知道该集合中只能存储哪些东西
是java.util.ArrayList
包下面的,底层由大小可变的数组 组成,存储的数据称为元素
该类中提供了一些操作元素的方法
ArrayList<数据类型> 集合名称 = new ArrayList<>();
public boolean add(E e) 返回布尔值,true添加成功
//数组声明时,需要指定长度
Person[] p1 = new Person[6];
p1[0] = new Person("战士", 23);
//集合声明
// ArrayList<数据类型> 集合名称 = new ArrayList<>();
ArrayList<Person> list = new ArrayList<>();
//集合添加元素
// public boolean add(E e) 返回布尔值,true添加成功
list.add(new Person("list", 23));
ArrayList<String> peopleNameList = new ArrayList<>();
peopleNameList.add("刘备");
peopleNameList.add("关羽");
peopleNameList.add("张飞");
for (String x : peopleNameList) {
System.out.println(x);
}
public class Animals {
private String color;
private Double weight;
public Animals(String color, Double weight) {
this.color = color;
this.weight = weight;
}
@Override
public String toString() {
return "Animals{" +
"color='" + color + '\'' +
", weight='" + weight + "kg" + '\'' +
'}';
}
}
ArrayList<Animals> animalsList = new ArrayList<>();
animalsList.add(new Animals("红色", 34.4));
animalsList.add(new Animals("黑色", 20.4));
animalsList.add(new Animals("橘色", 10.2));
for (Animals a : animalsList) {
System.out.println(a);
}
根据元素下标删除,返回删除的元素
public E remove(int index)
ArrayList<String> list = new ArrayList<>();
list.add("2");
list.add("3");
list.add("5");
String str = list.remove(0);
System.out.println(str);
通过下标获取
public E get(int index)
ArrayList<String> list=new ArrayList<>();
list.add("5");
list.add("6");
list.add("57");
list.add("8");
String s=list.get(1);
System.out.println(s);
public int size()
ArrayList<String> list=new ArrayList<>();
list.add("5");
list.add("6");
list.add("57");
list.add("8");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
jdk1.5
可用来遍历集合,数组;
注意:不要在遍历的过程中对集合进行增删操作!!!
内部采用了迭代器
for(被遍历集合元素类型 变量名称 : 集合的名称){
//code
}
Iterator<E> iterator()
// E next(); 表示下一个元素
// boolean hasNext(); 判断迭代器里面是否有元素
// void remove();
//迭代器遍历
Iterator<Integer> iterator = newNumInter.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
public class Phone {
private String brand;
private String color;
private double price;
public Phone(String brand, String color, double price) {
this.brand = brand;
this.color = color;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Phone{" +
"brand='" + brand + '\'' +
", color='" + color + '\'' +
", price=" + price +
'}';
}
}
public class Get {
public static void main(String[] args) {
ArrayList<Phone> arrayListPhone=new ArrayList<>();
arrayListPhone.add(new Phone("苹果","白色",6999));
arrayListPhone.add(new Phone("华为","黑色",8999));
arrayListPhone.add(new Phone("小米","蓝色",3999));
arrayListPhone.add(new Phone("vivo","黄色",1999));
System.out.println("删除前");
for (int i = 0; i < arrayListPhone.size(); i++) {
System.out.println(arrayListPhone.get(i)+"\t");
}
for (int i = 0; i < arrayListPhone.size(); i++) {
Phone p=arrayListPhone.get(i);
if(p.getBrand().equals("华为")){
p.setPrice(1);
}
if(p.getBrand().equals("vivo")){
arrayListPhone.remove(i);
}
}
System.out.println("删除后");
for (int i = 0; i < arrayListPhone.size(); i++) {
System.out.println(arrayListPhone.get(i)+"\t");
}
}
}
List<Integer> stringList = new ArrayList<>();
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
stringList.add(0);
//modCount防止同时操作集合,快速失败
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
private Object[] grow() {
return grow(size + 1);
}
//当List为空时,默认最小长度为10,否则扩容大概1.5倍 {>>}
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
if (newLength - MAX_ARRAY_LENGTH <= 0) {
return newLength;
}
return hugeLength(oldLength, minGrowth);
}
//注意长度最大限制
private static int hugeLength(int oldLength, int minGrowth) {
int minLength = oldLength + minGrowth;
if (minLength < 0) { // overflow
throw new OutOfMemoryError("Required array length too large");
}
if (minLength <= MAX_ARRAY_LENGTH) {
return MAX_ARRAY_LENGTH;
}
return Integer.MAX_VALUE;
}
stringList.remove(0);
- 排列有序,可重复
- 底层采用双向循环链表
- 查询速度慢,增删快
add(),remove()
- 线程不安全
- 离散空间,不需要主动扩容,无扩容机制
由于LinkedList采用了链表,增加了一些对链表的操作:
-
public void addFirst(E e)
在该列表开头插入指定的元素。 -
public void addLast(E e)
将指定的元素追加到此列表的末尾。 -
public E getFirst()
返回此列表中的第一个元素。 -
public E getLast()
返回此列表中的最后一个元素。 -
public E peek()
检索但不删除此列表的头(第一个元素)。 -
public E poll()
检索并删除此列表的头(第一个元素)。 -
public void push(E e)
将元素推送到由此列表表示的堆栈上。换句话说,在该列表的前面插入元素。 -
public E pop()
从此列表表示的堆栈中弹出一个元素。换句话说,删除并返回此列表的第一个元素。
package com.datastructure.demo2;
import java.util.LinkedList;
/**
* @author 涂鏊飞tu_aofei@163.com
* @description: TODO 类描述
* @create 2021-08-09 11:09
*/
public class Demo {
public static void main(String[] args) {
LinkedList<String> list=new LinkedList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//在头部添加元素
list.addFirst("fff");
System.out.println(list);
//在尾部添加元素
list.addLast("ggg");
System.out.println(list);
//得到第一个元素
System.out.println(list.getFirst());
//得到最后一个元素
System.out.println(list.getLast());
//得到头部元素
System.out.println(list.peek());
//得到头部第一个元素,并删除
list.poll();
System.out.println(list);
//头部添加元素
list.push("yyy");
System.out.println(list);
//删除第一个元素
list.pop();
System.out.println(list);
}
}
-
排列有序,可重复
-
底层使用数组
-
速度快,增删慢
-
线程安全,效率低
-
容量不够时,自动扩容,比例:
当前容量* 2
-
不允许存储重复的元素
-
没有索引的,没有和索引相关的方法,也不能使用普通的for循环遍历
存储的元素是无序的 ,不可重复的 ,底层使用的是hash
表 ,内部采用hashmap
线程不安全
HashSet 首先判断两个元素的哈希值,如果哈希值一样,接着会比较 equals 方法 如果 equls 结果为 true ,HashSet 就视为同一个元素。如果 equals 为 false 就不是 同一个元素。
当存储元素的时候会比较内容的hashcode值如果相同会覆盖原来的位置
//常用方法 添加 遍历 迭代器
public class SetDemo {
public static void main(String[] args){
Set<String> set=new HashSet<>();
//添加元素
set.add("aaa");
set.add("bbb");
set.add("ccc");
//遍历
for (String s : set) {
System.out.println(s);
}
//迭代器遍历
Iterator<String> iterator=set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
//内容不同,hashcode值相同 先比较hashcode,再比较equals
public class HashSetDemo {
public static void main(String[] args){
Set<String> set=new HashSet<>();
String st1=new String("abc");
String st2=new String("abc");
set.add(st1);
set.add(st2);
System.out.println(set);
System.out.println(st1.hashCode());
System.out.println(st2.hashCode());
System.out.println("重地".hashCode());
System.out.println("通话".hashCode());
set.add("重地");
set.add("通话");
System.out.println(set);
}
}
//对象hashcode值不同,内容相同 重写hashcode方法
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class DemoPerson {
/*
要重写person的hashcode方法
*/
public static void main(String[] args){
Set<Person> set=new HashSet<>();
Person p1=new Person("张三",18);
Person p2=new Person("李四",19);
set.add(p1);
set.add(p2);
System.out.println(set);
Person p3=new Person("小美女",18);
Person p4=new Person("小美女",18);
set.add(p3);
set.add(p4);
System.out.println(p3.hashCode());
System.out.println(p4.hashCode());
System.out.println(set);
}
}
存储的元素是无序的 ,不可重复的 ,底层使用的是二叉树 ,排序存储 ,内部采用了treemap
的 sortedset
线程不安全
public class TreeSet {
public static void main(String[] args) {
Set<String> set = new TreeSet<>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
System.out.println(set);
}
}
采用了hash
表 存储,但是用了链表来记录存储的数据 ,使得存入数据与取出数据变的有序,内部使用的是linkedhashmap
线程不安全
继承于hashSet
、又基于 LinkedHashMap
来实现的
LinkedHashSet 底层使用 LinkedHashMap 来保存所有元素,它继承与 HashSet,其所有的方法 操作上又与 HashSet 相同
public class LinkedHashSetDemo {
public static void main(String[] args) {
HashSet<String> st1=new HashSet<>();
st1.add("w22");
st1.add("bbb");
st1.add("ccc");
System.out.println(st1);
LinkedHashSet<String> st2=new LinkedHashSet<>();
st2.add("w22");
st2.add("bbb");
st2.add("ccc");
System.out.println(st2);
}
}
public static <T> boolean addAll(Collection<? super T> c,T... elements)
往集合中添加元素
public static void shuffle(List<?> list)
使用默认的随机源随机排列指定的列表。 所有排列都以大致相等的可能性发生。
public static <T extends Comparable<? super T>> void sort(List<T> list)
根据其元素的natural ordering,将指定的列表按升序排序。
//自定义类比较,实现Comparable接口,重写compareTo方法
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + 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;
}
/**
* description: TODO
*
* @since: 1.0.0
* @author: 涂鏊飞tuao_fei@163.com
* @date: 2021/8/10 10:38
* @Param o:
* @return: int
* 0表示两个元素相等
* 负值:降序
* 正值:升序
*/
@Override
public int compareTo(Person o) {
// return this.getAge() - o.getAge();
return o.getAge() - this.getAge();
}
}
public class DemoPerson {
public static void main(String[] args) {
List<Person> list=new ArrayList<>();
list.add(new Person("张三",18));
list.add(new Person("李四",17));
list.add(new Person("王五",15));
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
Integer 和 String 对象都可以进行默认的 TreeSet 排序,而自定义类的对象是不可以的,自己定义的类必须实现 Comparable 接口 ,并且覆写相应的 compareTo()
函数,才可以正常使用。
如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
//使用匿名类Comparator
public class Athletes /*implements Comparable<Athletes>*/{
private String name;
private int zj;
private int jt;
private int sumScore;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getZj() {
return zj;
}
public void setZj(int zj) {
this.zj = zj;
}
public int getJt() {
return jt;
}
public void setJt(int jt) {
this.jt = jt;
}
public int getSumScore() {
return sumScore;
}
public Athletes(String name, int zj, int jt) {
this.name = name;
this.zj = zj;
this.jt = jt;
this.sumScore = zj + jt;
}
@Override
public String toString() {
return "Athletes{" +
"name='" + name + '\'' +
", zj=" + zj +
", jt=" + jt +
", sumScore=" + sumScore +
'}';
}
// @Override
// public int compareTo(Athletes o) {
// return this.getSumScore()-o.getSumScore();
// }
}
public class Test3 {
public static void main(String[] args) {
LinkedList<Athletes> list=new LinkedList<>();
Collections.addAll(list,
new Athletes("颤三",125,264),
new Athletes("李四",251,251),
new Athletes("王五",235,240)
);
System.out.println(getMax(list));
}
public static Athletes getMax(LinkedList<Athletes> list){
// Collections.sort(list);
Collections.sort(list, new Comparator<Athletes>() {
@Override
public int compare(Athletes o1, Athletes o2) {
return o1.getSumScore()-o2.getSumScore();
}
});
System.out.println(list);
return list.getLast();
}
}
多条件排序
//排序:日期,班次,制丝线,升序排序
负数:升序,正数:降序
if (WsdCollectionUtils.isNotEmpty(res)) {
Collections.sort(res, (o1, o2) -> {
String workDate1 = o1.getWorkDate();
String workDate2 = o2.getWorkDate();
int i1 = workDate1.compareTo(workDate2);
String classLabel1 = o1.getClassLabel();
String classLabel2 = o2.getClassLabel();
int i2 = classLabel1.compareTo(classLabel2);
String lineCode1 = o1.getLineCode();
String lineCode2 = o2.getLineCode();
int i3 = lineCode1.compareTo(lineCode2);
if (i1 == 0) {
if (i2 == 0) {
return i3;
}
return i2;
}
return i1;
});
}
Map<k,v>
-
Map集合是一个双列集合 ,一个元素包含两个值k,v
-
Map集合中的元素,key和value的数据类型可以相同也可以不同
-
Map集合中的元素,key不能重复 ,value可以重复
-
Map集合中的元素,key和value是一一对应的
底层使用了hash
表 ,查询速度特别快
JDK1.8以前使用hash表+链表
JDK1.8以后使用hash表+链表 (红黑树 :当链表长度超过8 时)
线程不安全 ,key和value都可以存储 null
值
//声明Map
Map<String,String> map=new HashMap<>();
Map<Person,Integer> map1=new HashMap<>();
//添加
map.put("41151","张三");
map.put("41151","李四"); // 相当于修改,会覆盖原来的位置
map1.put(new Person(),25);
// V remove(Object key) 删除元素
String s = map.remove("郭靖");
System.out.println(s);
// V get(Object key) 通过集合中的key值,获取对应的value
String value = map.get("郭靖");
System.out.println(value);
// 判断是否包含对应的键和值
boolean b = map.containsKey("杨过");
System.out.println(b);
boolean b1 = map.containsValue("小龙女");
System.out.println(b1);
- 通过键找值
Set<K> KeySet()
通过该方法返回映射中所有键的set视图
-
通过使用map集合中KeySet方法,把map集合中的所有key值获取,存到set集合中
-
遍历set集合,获取map集合中的每一个key
-
通过map集合中的get(key),通过key找到value
Map<String, Integer> map = new HashMap<>();
map.put("武汉", 18);
map.put("武汉", 20);
System.out.println(map);
map.put("南京", 50);
map.put("扬州", 50);
System.out.println(map);
// 获取key值
Set<String> keySet = map.keySet();
for (String s : keySet) {
//根据get得到value
Integer value=map.get(s);
System.out.println("key:"+s+",value:"+value);
}
//简化写法
for (String s : map.keySet()) {
System.out.println("key:"+s+",value:"+map.get(s));
}
-
使用Map集合中的
Set<Map.Entry<K,V>> entrySet();
返回此映射中包含的映射关系的set视图 -
使用Map集合中的方法entrySet(),把Map集合中的多个entry对象取出来,存到set集合中
-
遍历set集合,获取每一个Entry对象
-
使用Entry对象中的方法getKey()和getValue(),分别获取键和值
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key=entry.getKey();
Integer value=entry.getValue();
System.out.println("key:"+key+",value:"+value);
}
线程安全 ,key和value不可以存储null值 存放的是无序不可重复的键值对
JDK1.2以后被hashmap替换,有一个子类Properties
依然在使用
Properties对象是唯一一个集合和IO相结合的集合
Map<String,Integer> map=new Hashtable<>();
map.put("站撒",13);
map.put("李四",14);
map.put("网袜",15);
// map.put(null,null); Hashtable中key和value都不能为null
System.out.println(map);
Map<String,Boolean> map1=new HashMap<>();
map1.put(null,null);
底层使用二叉树
线程不安全
Map<String,Integer> map=new TreeMap<>();
map.put("张三",18);
map.put("李四",25);
System.out.println(map);
底层采用hash表+链表
保存了记录的插入顺序
线程不安全
LinkedHashMap<String,Integer> map=new LinkedHashMap<>();
map.put("张三",26);
map.put("前进",65);
map.put("后退",56);
System.out.println(map);
System.out.println("请输入字符串:");
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
Map<Character, Integer> map = new HashMap<>();
for (char c : str.toCharArray()) {
//如果包含键c
if (map.containsKey(c)) {
//拿到键对应的值
Integer value = map.get(c);
// ++
value++;
// 覆盖
map.put(c,value);
} else {
//没有出现过,初始值1
map.put(c, 1);
}
}
for (Character character : map.keySet()) {
System.out.println("key:"+character+",value:"+map.get(character));
}
#当key相同时,去前或者后面的一位
list.stream().collect(Collectors.toMap(item -> item.getXXX(), item -> item, (oldVal, newVal) -> newVal));
#某个属性累加
list.stream().map(Object::getXXX).reduce(BigDecimal.ZERO, BigDecimal::add);
#最小的值
list.stream().min(Comparator.comparing(Object::getXXX)).get();
#最大的值
list.stream().max(Comparator.comparing(Object::getXXX)).get();
#list分组对value排序
TreeMap<String, List<Object>> map = list.stream().collect(Collectors.groupingBy(item -> WsdDateUtils.dateToStr(item.getXXX(), "yyyy-MM-dd"), TreeMap::new, Collectors.toList()));
#对map的value排序
ArrayList<Map.Entry<String, Integer>> entries = new ArrayList<>(defectMap.entrySet());
Collections.sort(entries, Comparator.comparing(Map.Entry::getValue));
#list分组分别对key和value排序
/**
* Map通过key进行排序
* @param map
* @param isDesc
* @param <K>
* @param <V>
* @return
*/
public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
Map<K, V> result = new LinkedHashMap<>();
if (isDesc) {
map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
} else {
map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey())
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
}
return result;
}
把 "map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())" 里面的
comparingByKey()换成comparingByValue() 就是根据 value 来排序