集合(容器)
数组:
存储相同类型的指定数组空间个元素数据。 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);
}
源码分析
2. LinkedList<T>
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
Queue: 队列
双链表实现了List和Deque接口。 实现所有可选列表操作,并允许所有元素(包括null )。
private static void testLinkedList() {
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("a");
linkedList.addFirst("b");
linkedList.add(0, "c");
linkedList.addLast("d");
// System.out.println(linkedList.remove());
// System.out.println(linkedList.remove(0));
// System.out.println(linkedList.removeFirst());
// System.out.println(linkedList.poll());
// System.out.println(linkedList.pollFirst());
// System.out.println(linkedList.pop());
// System.out.println(linkedList.get(0));
// System.out.println(linkedList.peek());
// System.out.println(linkedList.peekFirst());
// System.out.println(linkedList.getFirst());
// System.out.println(linkedList.get(linkedList.size() - 1));
// System.out.println(linkedList.getLast());
// System.out.println(linkedList.peekLast());
System.out.println(linkedList);
//index---> 不是数组的索引
//size/2
}
3. Vector<T>
4. CopyOnWriteArrayList<T>
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())
}
4. CopyOnWriteArraySet<T>
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);
}
2. LinkedHashMap<K,V>