一、数组
一片物理上连续,大小确定的存储空间
下标查找元素,时间上复杂度O(1)
按值查找,时间复杂度0(n)
1、定义数组
String[] arr=new String[]{"1","2","3"};
String[] arr2=new String[2];
String[][] arr3 = new String[3][5];
2、遍历数组
for (int i = 0; i < arr.length; i++) {
String temp = arr[i];
}
for(int m=0;m<arr3.length;m++){
for(int n=0;n<arr3[m].length;n++){
String value=arr3[m][n];
}
}
二、集合与数组
(1)集合与数组的区别
类别 | 长度 | 元素类型 |
数组 | 不可变的 | 基本数据类型,引用类型 |
集合 | 可变 | 引用类型 |
(2)集合与数组的转换
//数组----->集合Arrays.asList();
String[] arr=new String[10];
List<String> list=Arrays.asList(arr);
//集合------>数组 toArray();
List<String> list=new ArrayList<>();
String[] arr = (String[])list.toArray();
三、集合
1、集合的框架图
2、Collection是集合的顶层类
通用方法:
public booelan add(E e);
public void clear();
public booelan remove(E e);
public boolean contains(E e);
public boolean isEmpty();
public int size();
public Object[] toArray();
public Iterator<E> iterator();
3、元素遍历方式
(1)Iterator迭代器
在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,然后继续判断,继续取,一直把集合中的所有元素全部取出来。在迭代时可以删除元素。
主要方法:
public booelan hasNext();
E next();
用法实例:
List<String> list=new ArrayList<>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String temp=iterator.next();
}
(2)增强for也称foreach
注:在循环时不能增删,会发生下标越界错误
for(String item:list){
System.out.println(item);
}
4、Queue队列先进先出
E element() //检索,但不删除此队列的头
boolean offer(E e)//如果可能立即在不违反容量限制的情况下这样做的话,将指定的元素插入到队列
中。
E peek(); //检索,但不删除,这个队列头,或返回 null如果队列为空。
E poll(); //检索并移除此队列的头,或返回 null如果队列为空。
E remove(); //检索和删除此队列的头
四、List
三大特点:有序、元素可以重复、有索引
方法:除了Collection提供的方法,还包括些自己的方法
void add(int index,E element);
addAll(Collection<? extends E> c)
boolean containsAll(Collection<?> c)
E get(int index)
int indexOf(Object o)
E remove(int index)
boolean removeAll(Collection<?> c)
E set(int index, E element)
类名 | 底层实现 | 特点 | 父类 |
ArrayList | 数组 | 查询快,增删慢,线程不安全,默认容量10,扩容1.5倍 | List |
Vector | 数组 | 查询快,增删慢,线程安全 | List |
LinkedList | 链表 | 查询快,增删慢,线程不安全 | List,Queue |
Stack | 后进先出 | Vector |
1、ArrayList增删慢的原因?
- add(int index,E element)在指定下标插入元素,实现是该下标后面的元素都后移一位。
- remove(int index)删除指定下标元素,该下标之后的元素都要前进一位
- arrayList清除从后面删除
2、LinkedList的方法
void addFirst(E e) //在此列表的开始处插入指定的元素。
void addLast(E e) //将指定的元素列表的结束。
E getFirst()
E getLast()
boolean offer(E e) //将指定的元素添加到列表的尾部(最后一个元素)。
boolean offerFirst(E e)
boolean offerLast(E e)
E peek() 检索,但不删除,此列表的头(第一个元素)。
E peekFirst()
E peekLast()
E poll() 检索并删除此列表的头(第一个元素)。
E pollFirst()
E pollLast()
E pop() 从这个列表所表示的堆栈中弹出一个元素。
void push(E e)
3、Stack的方法
E peek 查看此堆栈顶部的对象,而不将它从堆栈中删除。
E pop() 在这个堆栈的顶部删除对象,并返回该对象的值作为该函数的值。
E push(E item) 将一个项目推到这个堆栈的顶部。
五、Set
特点:无序,元素唯一,无索引
类名 | 底层 | 特点 | 父类 |
HashSet | 哈希表 | 查询速度快,线程不安全,初始是16 | Set |
LinkedHashSet | 哈希表+链表 | 元素有序 | HashSet |
TreeSet | 红黑树 |
1、HashSet
为了保证元素的唯一性,依赖元素类的两个方法 hashCode方法和equals方法
哈希值是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址。是模拟出来得到地址,不是
数据实际存储的物理地址)在Object类中有一个方法可以获取对象的哈希值 int hashCode()返回对象的哈希码值。
jdk1.8版本之前:哈希表=数组+链表
jdk1.8版本之后:哈希表=数组+链表
哈希表=数组+红黑树(提高查询的速度)
哈希表的存储结构:
2、LinkedHashSet
底层:哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序,但也不允许重复
由链表保证元素有序,由哈希表保证元素唯一
3、TreeSet
底层:红黑树(唯一,有序)
为了保证元素排序,自然排序(元素具有比较性),比较器排序
(1)自然排序,compareTo方法
//实现Comparable接口,
public class Stundent implements Comparable<Stundent> {
@Override
public int compareTo(@NonNull Stundent o) {
return 0;
}
}
(2)使用比较器 Comparator接口
//构造器函数中传入实现了comparator接口
TreeSet<Student> set=new TreeSet<Student>(new Comparator<Student>(){
@Override
public int compare(Student o1, Student o2) {
return 0;
}
});
六、Map
1、映射键到值的对象。一张Map不能包含重复的键(键唯一),每个键可以映射到至多一个值
常用方法:
void clear()
boolean containsKey(Object key)
boolean containsValue(Object value)
Set<Map.Entry<K,V>> entrySet()
V get(Object key)
boolean isEmpty()
Set<K> keySet()
V put(K key, V value)
V remove(Object key)
int size()
2、Map.Entry<K,V>
接口Entry是Map的静态内部接口,键值对
final K key;
V value;
final int hash;
HashMapEntry<K, V> next;
K getKey() 返回对应于此项的键。
V getValue() 返回对应于此项的值。
V setValue(V value) 用指定的值替换对应于此项的值(可选操作)
3、map的遍历
(1)获取keyset
Map<String, String> maps = new HashMap<>();
Set<String> keySet = maps.keySet();
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String value = maps.get(key);
}
(2)获取entrySet
Map<String, String> maps = new HashMap<>();
Set<Map.Entry<String, String>> entries = maps.entrySet();
Iterator<Map.Entry<String, String>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
String key = entry.getKey();
String value = entry.getValue();
}
4、对比
类名 | 底层 | 特点 | 备注 |
HashMap | 数组+链表(数组+红黑树) | null键null值,线程不安全,无序 | |
LinkedHashMap | 数组+链表+链表 | 线程不安全,有序 | |
HashTable | 哈希表 | 不允许null键null值,线程安全,无序 | |
TreeMap | 二叉树 | 线程不安全 |
(1)HashMap
JDK1.8之前:数组+单向链表,JDK1.8之后:数组+单向链表/红黑树(链表的长度超过8)
七、HashMap原理解析
1、HashMap的底层(数组+链表)
- HashMap的主干是一个Entry数组,整体结构如下:
- Entry的结构
final int hash;
final K key;
V value;
Node<K,V> next;
- 数组确定下标
首先获取key对象的hashCode值,hashCode与数组长度的位运算获取下标,这就是元素的下标。
注:java中所有类都继承于Object类,可以覆写hashCode方法,这是一个native方法。
- 链表是为了解决哈希冲突
hashCode值不同,运算出来的下标有可能相同,所以需要用链表来解决hash冲突来存储数据。下标确定之后,获取当前下标链表,遍历链表,看是否存在entry,这个entry和要插入(查找)的entry的key值是否一样(这就是key值是唯一的原因),如果没有,则这个新entry的next的值为链表的头结点,形成新的链表返回。
2、HashMap扩容,阈值0.75f
初始值是16,newSize=oldSize*2,容量一定为2的n次幂,当map中的元素总数超过容量的75%,触发扩容,扩容的时候回遍历所有的元素重新计算元素下标,添加到新的链表。
Hashmap 优化,因为在扩容时浪费时间性能,所以可以在创建HashMap的时候指定大小,如果想要容量是10,设置值为10/0.75=14。
3、算法应用
集合去重
八、HashMap的扩展
1、LinkedHashMap
LinkedHashMap继承与HashMap,元素是有序的。
(1)LinkedHashMap的entry,双向链表
static class LinkedHashMapEntry<K,V> extends HashMap.Node<K,V> {
LinkedHashMapEntry<K,V> before, after;
LinkedHashMapEntry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
所以,每个Entry都包含 hash,key,value,Node,before,after
(2)LinkedHashMap初始化
- initialCapacity 初始化容量
- accessOrder 值为false时,插入排序;值为true时,访问排序
2、ConcurrentHashMap
ConcurrentHashMap底层是数组+链表,和HashMap和HashTable是一样的,但是HashMap是线程不安全的,hashTable是线程安全的,但是性能太差,而ConcurrentHashMap不仅是线程安全而且性能更高。
锁分段技术,通过把整个Map分成N个segment,可以提供相同的线程安全,但是效率提高N倍。
3、SparseArray
它是android内部特有的api,他 比HashMap更省内存,因为它的键只能是Interger,避免了对key的自动装箱。内部是通过两个数组来今次那个数据存储的,一个存储key,一个存储value。
private int[] mKeys;
private Object[] mValues;
key的查找是二分查找,value的值是和key的下标一样的。
sparseArray的添加时,后面的元素是以此向后移动,
删除时,并不会真的删除,是把value的设置为null。
九、Collections工具类
//指定列表为升序排序,根据其元素的 natural ordering。
static <T extends Comparable<? super T>> void sort(List<T> list)
//根据指定的比较器指定的顺序对指定的列表进行排序。
static <T> void sort(List<T> list, Comparator<? super T> c)