JAVA---Collection和Map区别

1. Collection<T>

 

==元素都是单值==

 元素是否有序元素是否可重复
List<T> 有序(所有的元素都有索引位置) 可以
Set<T> 无序(没有索引位置) 不可以

1.1. List<T>

 

默认创建时没有给集合大小 数据结构线程安全效率
ArrayList<T>初次扩容10,之后按1.5倍扩容 动态数组 查/修改快 新增和删除慢
LinkedList<T> 双向链表 新增/删除快 查/修改慢
Vector<T>初次扩容10,之后按2倍扩容,增量为0 动态数组 性能一般
CopyonWriteArrayList<T>初次扩容10,之后每次+1 动态数组 性能最慢

 

1.2. Set<T>

 

默认创建时没有给集合大小  数据结构线程安全元素是否可以为null
HashSet初次扩容16达到阈值两倍扩容 HashMap(数组+单向链表+红黑树) 可以
LinkedHashSet HashMap 可以
TreeSet初次扩容16达到阈值两倍扩容 红黑树 TreeMap 不可以
CopyOnWriteArraySet 动态数组 是 Lock 可以

 

2. Map<K,V>

 

默认创建时没有给集合大小  数据结构线程安全key/value是否可以为null
HashMap次扩容16达到阈值,两倍扩容 位桶(数组)+单向链表+红黑树 k/v 都可以
LinkedHashMap 位桶+双向链表+红黑树 k/v 都可以
TreeMap初次扩容16达到阈值,两倍扩容 红黑树 k不可以 v 可以
HashTable初次扩容11达到阈值,两倍+1扩容 jdk1.8位桶+单向链表+红黑树 k/v 都不可以

ConcurrentHashmap初次扩容16,

达到阈值之后两倍扩容

jdk1.7 锁分段技术 segment jdk1.8 CAS

 分段的数组+链表

k/v 都不可以
CAS:
 compare and  swap  比较并交换  乐观锁  认为任何操作都不会出现问题  效率很快  查询的场景
    多读少写 ----->  Redis 缓存 (主从同步)  
     
synchornized:
  同步锁  悲观锁  互斥锁  可重入锁

 

 

 

集合(容器)

数组:
 存储相同类型的指定数组空间个元素数据。  length  基本+引用
新增: 手动扩容
删除: 后面元素循环移位
查询/修改: 效率最快  index  
   
集合:
 理论上存储不同类型的不定量元素数据。 实际开发中 还是存储相同类型的数据。 <T>
 元素: 存储引用类型的数据。
     
<T>: 泛型的标志   类型的自动转换
  A-Z:   T  E  K  V  参数化类型----> 传递
     
集合里面使用泛型:
  集合元素数据有了限定。只能存储参数化的真实类型的数据。

 

集合分类:

1. Collection<T>
   1. 元素都是单值   2. 元素有序(索引位置)/是否可重复  不定
2. Map<K,V>
   1. 元素是一组元素  键值对 key:value
   2. key: 必须唯一 (不可重复)   value: 可重复    

 

 

1. Collection<T>

==元素都是单值==

 元素是否有序元素是否可重复
List<T> 有序(所有的元素都有索引位置) 可以
Set<T> 无序(没有索引位置) 不可以

 

常用方法:

public interface Collection<E>  extends Iterable<E>
   
Iterable<T>: 提供了遍历集合元素的方式。
    Iterator<T> iterator()   迭代   获得指定集合的迭代器对象。(将集合的 元素都放到了迭代器里面了)
    default void forEach(Consumer<? super T> action) 循环遍历集合元素

 

新增/==遍历(查询)==-----> 数据在数据库----> sql

新增元素:
  boolean add(E e)  
 
删除元素:
  boolean remove(Object o)  
  default boolean removeIf(Predicate<? super E> filter)  删除满足条件的所有的元素
  void clear()   清空集合所有的元素
     
查询/遍历元素:
  Iterator<T> iterator()
       1. boolean hasNext() 判断指针之后是否有更多的元素需要迭代
       2. T next() 获得光标之后的数据
       3. void remove() 删除元素数据
     
  default void forEach(Consumer<? super T> action)  
           
判断:
 boolean contains(Object o)   判断集合里面是否包含指定的元素
 boolean isEmpty()  判断集合是否是空
 
获得集合的元素个数:
 int size()  
 
集合转数组
 Object[] toArray()  
 <T> T[] toArray(T[] a)   推荐使用    
     
default Stream<E> parallelStream()  并行化
default Stream<E> stream()   串行化    

 

 

2. List<T>

void add(int index, E element)  
   
E get(int index)  
   
ListIterator<E> listIterator()      

E remove(int index)  
   
E set(int index, E element)  
   
default void sort(Comparator<? super E> c)  
   
List<E> subList(int fromIndex, int toIndex)      

 

 数据结构线程安全效率
ArrayList<T> 动态数组 查/修改 新增和删除慢
LinkedList<T> 双向链表 新增/删除快 查/修改慢
Vector<T> 动态数组 性能一般
CopyonWriteArrayList<T> 动态数组 性能最慢

 

链表结构:
 单向链表:
      元素数据element    下一个元素引用 next
 双向链表:
    上一个元素的引用 prev  元素数据element   下一个元素引用 next          

 

 

==1. ArrayList<T>==

public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
   
RandomAccess: 标识接口  快速随机访问     表明这个类的查询很快。
   
ArrayList() 初始化10 (数组)
ArrayList(int initialCapacity)    
   initialCapacity = 存储元素的最大个数/负载因子+1

 

使用方法

private static void testArrayList() {

       //创建List集合对象
       ArrayList<Integer> list = new ArrayList<>(10);
       list.add(10);
       list.add(11);// 0-size
       list.add(20);
       list.add(10);

       System.out.println(list);
       System.out.println(list.size());

       //删除
       // list.remove(new Integer(1));
       //list.set(list.size() - 1, 300);

       //遍历
//       for (Integer integer : list) {
//           System.out.println(integer);
//       }
//
//       System.out.println("----------------------");
//       Iterator<Integer> it = list.iterator();
//       while (it.hasNext()) {
//           System.out.println(it.next());
//       }
//       System.out.println("----------------------");
//       list.forEach(System.out::println);
//       System.out.println("----------------------");
//       for (int i = 0; i < list.size(); i++) {
//           if(list.get(i).equals(10)){
//               list.remove(i);
//               i--;
//           }
//       }

       //subList(start,end)
       List<Integer> list1 = list.subList(0, 3);// view : 不能执行操作   看
       //操作list1 任何操作都会作用到原集合上面
       //list1.add(1000);
       //list1.remove(0);
       // list1.set(0, 1000);

       //操作原集合 报异常
       list = new ArrayList<>(list);
       list.add(0, 1000);

       System.out.println("list:" + list1);
       System.out.println(list);
  }

//服务于集合里面的快速失败的机制 fail-fast
//统计操作集合元素的次数(add/remove)
protected transient int modCount = 0;
private void ensureExplicitCapacity(int minCapacity) {//10
modCount++;

// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);//真正扩容逻辑实现在grow
}

private void grow(int minCapacity) {//10
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

2. LinkedList<T>

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
Queue: 队列

双链表实现了List和Deque接口。 实现所有可选列表操作,并允许所有元素(包括null )。

3. Vector<T>

 private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);// 2倍的扩容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}

 

 

2. Set<T>

 数据结构线程安全元素是否可以为null
HashSet HashMap(数组+单向链表+红黑树) 可以
LinkedHashSet HashMap 可以
TreeSet 红黑树 TreeMap 不可以
CopyOnWriteArraySet CopyOnWriteArrayList 是 Lock 可以

 

 

1. HashSet<T>

HashSet() 
构造一个新的空集合; 背景HashMap实例具有默认初始容量(16)和负载因子(0.75)。

HashSet(int initialCapacity) 16

 

private static void testHashSet() {

HashSet<Integer> hashSet = new HashSet<>(16);
//完全无序
hashSet.add(1);
hashSet.add(100);
hashSet.add(10);
hashSet.add(16);
hashSet.add(1000);
hashSet.add(null);

System.out.println(hashSet);

//遍历方式 与Collection一样
hashSet.forEach(System.out::println);

System.out.println("------------------");
Iterator<Integer> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}

 

 

2. LinkedHashSet<T>

元素有序。 新增的顺序与遍历顺序是一致的。

3. TreeSet<T>

排序。元素都是有序的 按照自然顺序进行排列。升序排列

TreeSet(Comparator<? super E> comparator) 自定义外部比较器

private static void testUsersTreeSet() {
//Exception in thread "main" java.lang.ClassCastException: com.javasm.util.User cannot be cast to java.lang.Comparable
//元素类型肯定要实现Comparable

TreeSet<User> treeSet = new TreeSet<>();
//效率慢

treeSet.add(new User(1, "admin", 30));
treeSet.add(new User(2, "admin", 18));
treeSet.add(new User(3, "张三", 20));
treeSet.add(new User(4, "李四", 18));
treeSet.add(new User(5, "王五", 22));
treeSet.add(new User(6, "admin", 17));
System.out.println(treeSet);
treeSet.forEach(System.out::println);

// System.out.println(treeSet.first())
}

3. Map<K,V>

 

key:value key: 唯一 value: 可重复的

 

 数据结构线程安全key/value是否可以为null
HashMap 位桶+单向链表+红黑树 k/v 都可以
LinkedHashMap 位桶+单向链表+红黑树 k/v 都可以
TreeMap 红黑树 k不可以 v 可以
HashTable hash表 k/v 都不可以
ConcurrentHashmap jdk1.7 锁分段技术 segment jdk1.8 CAS k/v 都不可以
CAS:
compare and swap 比较并交换 乐观锁 认为任何操作都不会出现问题 效率很快 查询的场景
多读少写 -----> Redis 缓存 (主从同步)

synchornized:
同步锁 悲观锁 互斥锁 可重入锁
V put(K key, V value)  增

V remove(Object key) 删
default boolean remove(Object key, Object value)

default V replace(K key, V value) 改
default boolean replace(K key, V oldValue, V newValue)

V get(Object key) 查
default V getOrDefault(Object key, V defaultValue)


Set<Map.Entry<K,V>> entrySet() 遍历 推荐
default void forEach(BiConsumer<? super K,? super V> action) 推荐
Set<K> keySet()

 

 

==1. HashMap<K,V>==

HashMap() 
构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。

HashMap(int initialCapacity)
构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。

 

使用方法

private static void testHashMap() {

//存储用户信息: Map的key几乎都是要String或者Integer 类似前端json的数据 key:value

HashMap<String, Object> hashMap = new HashMap<>(16);
//map的key重复了 值会被覆盖的
hashMap.put("id", 1001);
hashMap.put("name", "张三");
hashMap.put("age", 20);
hashMap.put("balance", 20000.776);

System.out.println(hashMap);


//删除
//System.out.println(hashMap.remove("age"));
//System.out.println(hashMap.remove("age",20));

//修改
//System.out.println(hashMap.replace("age", 21));
//System.out.println(hashMap.replace("age", 20,21));

//查询
// System.out.println(hashMap.get("name1"));
//System.out.println(hashMap.get("name1").equals("aaa"));

// System.out.println(hashMap.getOrDefault("name1", ""));

System.out.println(hashMap);
}

 

 private static void testHashMap1() {
HashMap<String, Object> hashMap = new HashMap<>(16);
hashMap.put("id", 1001);
hashMap.put("name", "张三");
hashMap.put("age", 20);
hashMap.put("balance", 20000.776);

//遍历map集合元素
// hashMap.forEach((key, value) -> {
// System.out.println(key + ":" + value);
// });


Set<Map.Entry<String, Object>> entrySet = hashMap.entrySet();
// 将map里面的每一组元素都封装成一个个的Entry对象 再将entry对象存储set集合
// Iterator<Map.Entry<String, Object>> iterator = entrySet.iterator();
// while (iterator.hasNext()) {
// Map.Entry<String, Object> entry = iterator.next();
// System.out.println(entry.getKey() + ":" + entry.getValue());
// }

// for (Map.Entry<String, Object> entry : entrySet) {
// System.out.println(entry.getKey() + ":" + entry.getValue());
// }

Set<String> keySet = hashMap.keySet();//将map里面所有的key存储在set集合中
for (String key : keySet) {
System.out.println(key+":"+hashMap.get(key));
}


}

 

private static void testDemo() {
String str = "abcvdg121111aaavvcc";
//使用hashmap 每个字符出现的次数
Map<String, Integer> map = new HashMap<>(16);

int length = str.length();
for (int index = 0; index < length; index++) {
String s = String.valueOf(str.charAt(index));//每个字符

/* if(!map.containsKey(s)){
map.put(s, 1);
}else{
map.put(s, map.get(s)+1);
}*/

//判断之前是否存储字符s
Integer count = map.get(s);
if (count == null) {
map.put(s, 1);
} else {
map.put(s, ++count);
}
}

System.out.println(map);
}

 

 

源码

1. HashMap解决hash冲突的方式
2. HashMap的扩容机制

 

//位桶(数组)+单向链表+红黑树

transient Node<K,V>[] table;//(位桶)数组 维护map集合里面部分元素 null
final float loadFactor;//负载因子 0.75

static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 初始化容量 16
static final int MAXIMUM_CAPACITY = 1 << 30;//最大容量

//单向链表上 7个的时候 (map的size>64) 会自动将链表转换成树结构
static final int TREEIFY_THRESHOLD = 8;//链表转树临界点
static final int UNTREEIFY_THRESHOLD = 6;//树转链表的临界点
static final int MIN_TREEIFY_CAPACITY = 64;

int threshold;// 阈yu值 临界点 再次扩容临界点 0 12

public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; //0.75F
}

 

//单向链表
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;// key的hash
final K key;//key的值
V value;
Node<K,V> next;//下一组元素的引用

Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}

 

public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
// 97 a 1
}
 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;//获得扩容之后数组的长度
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
//解决key值重复(解决hash冲突的方式)
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
// hash一致 元素数据不同
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}

 

 

 

2. TreeMap<K,V>

略 元素会按照自然顺序进行排列 要求TreeMap的key的类型必须要提供排序规则。

 

 

4. 排序

了解。

java.lang.Comparable<T> ----> compareTo()(内部比较器)
java.util.Comparator<T> ---->compare() 推荐(外部比较器)

 

1. List集合

实现Comparable

private static void demo2() {

//存储的自定义类对象
List<UserInfo> userInfoList = new ArrayList<>(10);

Collections.addAll(userInfoList,
new UserInfo(1, "jim1", 20),
new UserInfo(10, "jim2", 20),
new UserInfo(7, "jim3", 18),
new UserInfo(3, "jim4", 17)
);

userInfoList.forEach(System.out::println);

//按照年龄升序排列 年龄相等 按照id进行降序排列
Collections.sort(userInfoList);
System.out.println("------------------------");

userInfoList.forEach(System.out::println);
}

 

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
//高内聚 低耦合(层与层)
public class UserInfo implements Comparable<UserInfo> {

private Integer id;
private String name;
private Integer age;

@Override
public int compareTo(UserInfo userInfo) {
int result = this.age.compareTo(userInfo.age);//0 -1 1
if (result == 0) {
result = userInfo.id.compareTo(this.id);
}
return result;
}
}

使用Comparator

 private static void demo2() {

//存储的自定义类对象
List<UserInfo> userInfoList = new ArrayList<>(10);

Collections.addAll(userInfoList,
new UserInfo(1, "jim1", 20),
new UserInfo(10, "jim2", 20),
new UserInfo(7, "jim3", 18),
new UserInfo(3, "jim4", 17)
);

userInfoList.forEach(System.out::println);

//按照年龄升序排列 年龄相等 按照id进行降序排列
// Collections.sort(userInfoList);
//外部比较器
// userInfoList.sort(new Comparator<UserInfo>() {
// @Override
// public int compare(UserInfo user1, UserInfo user2) {
// int result = user1.getAge().compareTo(user2.getAge());
// if (result == 0) {
// result = user2.getId().compareTo(user1.getId());
// }
// return result;
// }
// });


// userInfoList.sort((user1, user2) -> {
// int result = user1.getAge().compareTo(user2.getAge());
// if (result == 0) {
// result = user2.getId().compareTo(user1.getId());
// }
// return result;
// });

userInfoList.sort(Comparator.comparing(UserInfo::getAge).reversed());

System.out.println("------------------------");

userInfoList.forEach(System.out::println);
}

 

2. Set集合

HashSet/LinkedHashSet TreeSet

private static void demo1() {

//HashSet/LinkedHashSet 完全无序 无法直接排序
Set<Integer> set = new HashSet<>(16);
Collections.addAll(set, 20, 1, 0, 100, 9, 8);
System.out.println(set);

//获得set集合元素的最值
Integer max = Collections.max(set);
System.out.println(max);
System.out.println(Collections.min(set));

//set转换List?
//List<Integer> list = new ArrayList<>(set);

//jdk1.8+ Stream---> 操作集合元素(类似于一个更加强大的Iterator)
List<Integer> collect = set.stream().sorted().collect(Collectors.toList());
System.out.println(collect);//[0, 1, 8, 9, 20, 100]
}

 

TreeSet

 private static void demo3() {
TreeSet<UserInfo> treeSet = new TreeSet<>(Comparator.comparing(UserInfo::getAge));
Collections.addAll(treeSet,
new UserInfo(1, "jim", 20),
new UserInfo(10, "jim", 20),
new UserInfo(7, "jim", 18),
new UserInfo(3, "jim", 17)
);

treeSet.forEach(System.out::println);

}

 

3. Map集合

key值排序 类似Set map集合key: String Long Integer

 

5. Collections

操作集合元素工具类。

static <T> boolean addAll(Collection<? super T> c, T... elements) ; 将元素存储集合中

static <T extends Comparable<? super T>> void sort(List<T> list) 排序
static <T> void sort(List<T> list, Comparator<? super T> c)

//将线程不安全的集合对象 转换成线程安全的集合对象
static <T> List<T> synchronizedList(List<T> list)
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

static void shuffle(List<?> list) 打乱集合元素顺序(类似于洗牌)

static <T extends Object & Comparable<? super T>>
T max(Collection<? extends T> coll)
static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)

 

==6. 集合嵌套==

public static void main(String[] args) {

//根据省份查询所有的城市信息====> 根据key获得value Map
Map<String, List<String>> provinceMap = new HashMap<>(16);

List<String> cityList = new ArrayList<>(10);
cityList.add("郑州1");
cityList.add("郑州2");
cityList.add("郑州3");
cityList.add("郑州4");
cityList.add("郑州5");

provinceMap.put("he", cityList);

cityList = new ArrayList<>(10);
cityList.add("济南1");
cityList.add("济南2");
cityList.add("济南3");
cityList.add("济南4");
cityList.add("济南5");

provinceMap.put("sd", cityList);

//获得he省份下所有的城市信息
List<String> list = provinceMap.get("sd");
System.out.println(list);


System.out.println("---------------------------------");

List<Map<String, Object>> list1 = new ArrayList<>();

//用户类: 属性:值 key:value

Map<String,Object> map = new HashMap<>();
map.put("username","admin");
map.put("id",10001);
map.put("roleName","管理员");

Map<String,Object> map1 = new HashMap<>();
map1.put("username","test");
map1.put("id",10001);
map1.put("roleName","test");

list1.add(map);
list1.add(map1);

list1.forEach(System.out::println);

}

 

 

==7. Stream==

jdk1.8+ 新特性 核心功能: 聚合数据 操作集合元素。

串行  vs 并行
串行: 线下完成 一个任务结束就是另外一个任务的开始。
并行: 多个任务同时执行的。

 

获得Stream对象的方式:
private static void demo2() {

//1. 集合里面的stream----> Collection
List<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();
Stream<Integer> stream1 = list.parallelStream();

//2. Stream接口的方法
Stream<Integer> stream2 = Stream.of(1, 2, 3);

//3. Arrays---> 基本数据类型Stream----> unboxed
IntStream intStream = Arrays.stream(new int[]{1, 2, 3});
Stream<Integer> boxed = intStream.boxed();

//4. Random
//获得1000-10000 5个随机的数字
Random random = new Random();
IntStream intStream1 = random.ints(5, 1000, 10001);

}

 

常用的方法

  1. filter() 过滤下来符合条件集合元素

 private static void demo3() {
List<UserInfo> userInfoList = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
userInfoList.add(new UserInfo(i, "张三" + i, +(1 + i)));
}
//过滤下来年龄>30用户对象
// List<UserInfo> userInfoList1 = new ArrayList<>(30);
// for (UserInfo userInfo : userInfoList) {
// if (userInfo.getAge() > 30) {
// userInfoList1.add(userInfo);
// }
// }
// userInfoList1.forEach(System.out::println);

//避免出现流中断: 链式调用方法
List<UserInfo> collect = userInfoList.parallelStream().filter(userInfo -> userInfo.getAge() > 30).collect(Collectors.toList());//中断
collect.forEach(System.out::println);
}

 

  1. flatMap() 多对一 将多个Stream转换成1个Stream

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)  
private static void demo5() {

//集合转数组 toArray
//数组转集合 Arrays.asList()

List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(10, 2, 30);
List<Integer> list3 = Arrays.asList(11, 21, 3, 7, 8);

//将list1 2 3 集合里面的 数据 去重 升序 转换到一个集合中

// Stream.of(list1, list2, list3).flatMap(new Function<List<Integer>, Stream<?>>() {
// @Override
// public Stream<?> apply(List<Integer> integers) {
// return null;
// }
// });

List<Integer> collect = Stream.of(list1, list2, list3).flatMap(List::parallelStream).distinct().sorted().collect(Collectors.toList());

System.out.println(collect);
}

 

map() 一对一 (每个元素都要参与运算) 一直使用的是同一个Stream对象

peek() 窥视 产生一个新的Stream对象

private static void demo6() {
List<UserInfo> userInfoList = new ArrayList<>(10);
Collections.addAll(userInfoList,
new UserInfo(1, "jim1", 20),
new UserInfo(10, "jim2", 20),
new UserInfo(7, "jim3", 18),
new UserInfo(3, "jim4", 17)
);

//将用户的名称全部在换大写
// for (UserInfo userInfo : userInfoList) {
// userInfo.setName(userInfo.getName().toUpperCase());
// userInfo.setAge(userInfo.getAge()+1);
// }
// userInfoList.forEach(System.out::println);

// userInfoList.parallelStream().map(new Function<UserInfo, UserInfo>() {
// @Override
// public UserInfo apply(UserInfo userInfo) {
// return null;
// }
// });

// userInfoList.parallelStream().peek(new Consumer<UserInfo>() {
// @Override
// public void accept(UserInfo userInfo) {
// userInfo.setName(userInfo.getName().toUpperCase());
// }
// });

// List<UserInfo> collect = userInfoList.parallelStream().map(user -> {
// user.setName(user.getName().toUpperCase());
// return user;
// }).collect(Collectors.toList());

// List<UserInfo> collect = userInfoList.parallelStream().peek(user -> user.setName(user.getName().toUpperCase())).collect(Collectors.toList());
// collect.forEach(System.out::println);

//获得所有用户name
// userInfoList.parallelStream().map(new Function<UserInfo, String>() {
// @Override
// public String apply(UserInfo userInfo) {
// return null;
// }
// });

// List<String> collect = userInfoList.parallelStream().map(userInfo ->userInfo.getName().toUpperCase()).collect(Collectors.toList());
// System.out.println(collect);

}

 

reduce() 聚合 多个元素参与运算 得到一个最终的结果 sum/avg/max/min

 private static void demo7() {

List<UserInfo> userInfoList = new ArrayList<>(10);
Collections.addAll(userInfoList,
new UserInfo(1, "jim1", 20),
new UserInfo(10, "jim2", 20),
new UserInfo(7, "jim3", 18),
new UserInfo(3, "jim4", 17)
);

//求年龄最大的
// userInfoList.parallelStream().reduce(new BinaryOperator<UserInfo>() {
// @Override
// public UserInfo apply(UserInfo userInfo, UserInfo userInfo2) {
// return null;
// }
// });

//Optional null判断 避免出现NPE
Optional<UserInfo> optionalInfo = userInfoList.parallelStream().reduce((user1, user2) -> {
if (user1.getAge().compareTo(user2.getAge()) > 0) {
return user1;
}
return user2;
});

UserInfo userInfo = optionalInfo.get();
System.out.println(userInfo);

System.out.println("--------------------------");
List<Integer> list = Arrays.asList(79, 90, 80);
// Integer result = list.parallelStream().reduce(Integer::sum).get();
// System.out.println(result);
// System.out.println(result / list.size());

// Integer result = list.parallelStream().reduce(0, Integer::sum);
// System.out.println(result);
}

 

8. Stream案例

@Setter
@Getter
@AllArgsConstructor
@ToString
@NoArgsConstructor
public class Node {// Child

private Integer id;//节点的id
private String name;//节点名称
private Integer pid;//父级节点
private List<Node> childNodeList;//当前节点的子级节点
}

 

public class StreamDemo2 {


//初始化家族数据
static List<Node> family;

static {
family = new ArrayList<>(10);

//节点的pid为0的时候 证明1级节点
//1级
family.add(new Node(1, "爷爷", 0, null));
family.add(new Node(2, "二爷", 0, null));
family.add(new Node(3, "三爷", 0, null));


//2级
family.add(new Node(4, "爷爷-son1", 1, null));
family.add(new Node(5, "爷爷-son2", 1, null));
family.add(new Node(6, "爷爷-son3", 1, null));
family.add(new Node(7, "二爷-son1", 2, null));
family.add(new Node(8, "二爷-son2", 2, null));
family.add(new Node(9, "三爷-son1", 3, null));


//3级
family.add(new Node(10, "爷爷-son1-son1", 4, null));
family.add(new Node(11, "二爷-son1-son1", 7, null));
family.add(new Node(12, "三爷-son1-son1", 9, null));
family.add(new Node(13, "三爷-son1-son2", 9, null));
}

public static void main(String[] args) {
//使用Stream的相关功能 展示层级关系
List<Node> nodeList = family.parallelStream()
.filter(node -> node.getPid().equals(0))
.peek(parentNode -> parentNode.setChildNodeList(selectChildNode(parentNode)))
.collect(Collectors.toList());
nodeList.forEach(System.out::println);
}

//递归
private static List<Node> selectChildNode(Node parentNode) {
return family.parallelStream()
.filter(node -> node.getPid().equals(parentNode.getId()))
.peek(child -> child.setChildNodeList(selectChildNode(child)))
.collect(Collectors.toList());
}

}
 



 

 


 实线继承,虚线实现          
 Collection体系

 

 

 
 
Map体系

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-10-21 18:25  学JAVA的旅行者  阅读(133)  评论(0)    收藏  举报