面向对象基础篇 – 集合与映射
Java数组
- 特点:
- 只有一个属性 .length长度
- 数组一旦确定 其长度不可改变
- 通过角标来访问元素
- 数组只能存储同一个数据类型
- 连续的变量空间
- 弊端:
- 如果要对其进行增删改查的操作时,得需要自己创建相对应的函数功能
集合
- 为了更方便的操作数据
提供一个容器用于存储数据,增加相对应的增删改查的方法,进行整体的封装->类
集合的目的就是为了管理元素(增删改查)
只不过对于容器而言,它不一定都是数组(链表、树、哈希表)
//所有集合的统称/父类 java.util.Collection
public interface Collection<E> extends Iterable<E>
- Iterable:可迭代的,实现该接口的子类,都可以进行内部元素的遍历,并且可以被foreach循环使用
方法
- boolean add(E e) 添加元素 成功返回true 否则返回false 表尾
- boolean addAll(Collection<? extends E> c) 将另一个集合中的所有元素添加进来 成功返回true 否则返回false
- void clear() 清空集合
- boolean contains(Object o) 是否包含某一个元素
- boolean containsAll(Collection<?> c) 是否包含指定集合中所有的元素
- boolean equals(Object o) 比的是两个集合的内容是否相等
- boolean isEmpty() 判断集合是否为空
- Iterator iterator() 返回该集合的迭代器
- boolean remove(Object o) 删除指定元素 成功返回true 否则返回false
- boolean removeAll(Collection<?> c) 删除指定集合中的所有元素
- boolean retainAll(Collection<?> c) 取交集
- int size() 获取集合中元素的个数
- Object[] toArray() 将所有元素打包成一个数组
- T[] toArray(T[] a) 将所有元素打包成一个数组
集合子接口 List < E >
- 支持角标操作,允许重复元素,允许null元素,一维数据
实现子类
- ArrayList
大小可变数组的实现
并允许包括 null 在内的所有元素 允许重复元素
不同步的 线程不安全 函数没有同步关键synchronized - 适用于单线程情况
ArrayList() 构造一个初始容量为 10 的空列表
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表。
ArrayList(Collection<? extends E> c) 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
public class CollectionDemo03 {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>(); //默认容量为10
ArrayList<Integer> list2 = new ArrayList<>(20);//指定容量为20
System.out.println(list1.size());
System.out.println(list2.size());
ArrayList<Integer> list3 = new ArrayList<>(list2);
for (int i = 1; i <= 12; i++) {
list1.add(i); //动态扩容 超了 每次+1
}
list1.ensureCapacity(20); //20 > 12 容量20
System.out.println(list1);
list1.remove(0);
list1.trimToSize(); //将列表的容量调整为元素的个数 容量12
ArrayList<Person> persons = new ArrayList<>();
persons.add(new Person("cat", 12));
persons.add(new Person("dog",22));
persons.add(new Person("abc",10));
System.out.println(persons.toString());
persons.sort(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getName().compareTo(o2.getName());
}
});
System.out.println(persons);
}
}
class Person implements Comparable<Person>{
private String name;
private int age;
//构造函数
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
System.out.println("person equals....");
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
System.out.println("person hashCode....");
return Objects.hash(name, 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;
}
@Override
public int compareTo(Person o) {
return name.compareTo(o.getName());
}
}
- Vector
大小可变数组的实现
并允许包括 null 在内的所有元素 允许重复元素
同步的 线程安全 函数有同步关键synchronized - 适用于多线程情况
- LinkedList
链接列表实现 双向循环链表 具有头尾指针的 first last
具有Queue队列功能
具有Deque双端队列功能
具有栈的功能
//力扣32题,最长有效括号
class Solution {
public int longestValidParentheses(String s) {
char[] arr = s.toCharArray();
LinkedList<Integer> stack = new LinkedList<>();
int maxLen = 0;
for (int i = 0; i < arr.length; i++) {
if(!stack.isEmpty()&&arr[i]==')'&&arr[stack.peek()]=='('){
stack.pop();
if(stack.isEmpty()) maxLen = Math.max(maxLen,i+1);
else maxLen = Math.max(maxLen,i-stack.peek());
continue;
}
stack.push(i);
}
return maxLen ;
}
}
- Stack
是Vector的子类 做为栈来使用的
大小可变数组的实现
并允许包括 null 在内的所有元素 允许重复元素
同步的 线程安全 函数有同步关键synchronized - 适用于多线程情况
集合子接口 Set < E >
- 不支持角标操作,不包含重复元素,允许null元素最多1个
实现子类
- TreeSet
底层数据结构-红黑树-二分搜索树
使用元素的自然顺序对元素进行排序 二分搜索树中序遍历是有序的
不同步的 线程不安全 函数没有同步关键synchronized - 适用于单线程情况
不允许存储null值 不允许重复
- HashSet
底层数据结构 数组(哈希表)+链表+红黑树 实现的 无序集合
平均每个链表长度>8的时候 每个链表转换为红黑树
平均每个红黑树长度<6的时候,每个红黑树转换为链表
本质上 哈希表 要么是一个链表的数组LinkedList[] 要么是红黑树的数组TreeSet[] 桶-容器
它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变
允许null值,禁止重复元素 线程不安全 不同步
默认初始容量是 16 数组的长度
默认的加载因子 0.75 桶的个数 / 桶中元素的个数
public static void main(String[] args) {
System.out.println("Pride and Prejudice");
ArrayList<String> words = new ArrayList<String>();
FileOperation.readFile("pride-and-prejudice.txt", words);
System.out.println("Total words:" + words.size());
HashSet<String> set = new HashSet<String>();
for (String word : words) {
set.add(word);
}
System.out.println("Total different words:" + set.size());
}
- LinkedHashSet
原理和用法和HashSet是一致的 是HashSet的子类
LinkedHashSet实现是LinkedHashMap的一种
此实现与 HashSet 的不同之外在于,LinkedHashSet维护着一个运行于所有条目的双重链接列表。
此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代
如果要求元素进入顺序和迭代顺序一致的话 LinkedHashSet
实际上就是HashSet + 双向链表 实现的
HashSet还是按照上述的内容进行元素管理
双向链表 专门用于按照进入顺序存储管理元素
集合子接口Queue < E >
- 描述队列的操作 先进先出
子接口 Deque < E >
- 是Queue的子接口 描述的是双端队列的操作 重点操作表的头尾
插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e)
移除 removeFirst() pollFirst() removeLast() pollLast()
检查 getFirst() peekFirst() getLast() peekLast()
Queue 方法 等效 Deque 方法
add(e) addLast(e)
offer(e) offerLast(e)
remove() removeFirst()
poll() pollFirst()
element() getFirst()
peek() peekFirst()堆栈方法 等效 Deque 方法
push(e) addFirst(e)
pop() removeFirst()
peek() peekFirst()
实现子类
- ArrayDeque
底层数组实现 不同步 禁止null
其他功能和LinkedList一模一样
可以把类理解为数组版的LinkedList
- PriorityQueue 优先队列
底层数据结构最小堆结构(最大堆)
本质上就是一个二叉树
二分搜索树特点:任何一个结点的左孩子比你小 右孩子比你大 底层实现 链表实现
最小堆特点:任何一个结点都比左右两个孩子小 完全二叉树 底层实现 数组实现
自然排序 禁止null 不同步
映射 Map
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值
键-值 key-value 键值对
key - 数组中的角标index
value - 数组中某一个角标对应的值arr[index]
从key-value 一对一的关系
多个key指向同一个value 多对一的关系
Collection只管存储元素
Map既要存储元素value 也要管理该元素对应的索引key(不可变类)
功能方法
void clear() 清空
boolean containsKey(Object key) 判断该key对应的键值对是否存在
boolean containsValue(Object value) 判断value是否存在于键值对中
Set keySet() 返回所有键的集合
Collection values() 返回所有值的集合
Set<Map.Entry<K,V>> entrySet() 返回所有键值对的集合
boolean equals(Object o) 比较指定的对象与此映射是否相等。
V get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
int hashCode() 返回此映射的哈希码值。
boolean isEmpty() 如果此映射未包含键-值映射关系,则返回 true。
V put(K key, V value) 不存在则添加-已存在则修改。
void putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)
V remove(Object key) 根据键删除键值对。
int size() 返回此映射中的键-值映射关系数。
实现子类
- TreeMap 红黑树 禁止null key禁止null 自然排序有序映射 不安全
下面这些函数的功能 参考TreeSet
Map.Entry<K,V> ceilingEntry(K key)
K ceilingKey(K key)
Map.Entry<K,V> floorEntry(K key)
K floorKey(K key)
Map.Entry<K,V> higherEntry(K key)
K higherKey(K key)
Map.Entry<K,V> lowerEntry(K key)
K lowerKey(K key)
Map.Entry<K,V> firstEntry()
K firstKey()
Map.Entry<K,V> lastEntry()
K lastKey()
Map.Entry<K,V> pollFirstEntry()
Map.Entry<K,V> pollLastEntry()
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
TreeMap<Integer, Integer> map=new TreeMap<Integer, Integer>();
for(int num:nums1){
if(!map.containsKey(num)){
map.put(num, 1);
}else{
map.put(num, map.get(num)+1);
}
}
ArrayList<Integer> list=new ArrayList<Integer>();
for(int num:nums2){
if(map.containsKey(num)){
list.add(num);
map.put(num, map.get(num)-1);
if(map.get(num)==0){
map.remove(num);
}
}
}
int[] res=new int[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i]=list.get(i);
}
return res;
}
}
- HashMap
底层 数组+链表/红黑树
允许null 键禁止null 无序 不安全
如果两个元素计算出来的哈希值和要去的哈希角标一致 称之为哈希冲突
HashMap中 解决哈希冲突的办法 链地址法 把哈希冲突的元素放到同一个桶里面
这个桶要么是个链表 要么是个红黑树
函数功能来自Map
-
LinkedHashMap 多了一个链表来管理元素的进入顺序 其他和HashMap一样的
-
Hashtable
底层 数组
禁止null 键禁止null 无序 不安全
如果两个元素计算出来的哈希值和要去的哈希角标一致 称之为哈希冲突
Hashtable中 解决哈希冲突的办法 开放地址法+二次哈希 将冲突的元素后置存放
将哈希冲突的元素进行后置存放,为了关联哈希值一样的元素,Entry结点中有一个next来进行关联元素
函数功能来自Map
- Properties
- ConcurrentHashMap
和HashMap一致
只有ConcurrentHashMap它是同步的 线程安全的
总结
Collections 集合的工具类
- static int binarySearch(List<? extends Comparable<? super T>> list, T key)
使用二分搜索法搜索指定列表,以获得指定对象。 - static int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
使用二分搜索法搜索指定列表,以获得指定对象。 - static <T extends Comparable<? super T>> void sort(List list)
根据元素的自然顺序 对指定列表按升序进行排序。 - static void sort(List list, Comparator<? super T> c)
根据指定比较器产生的顺序对指定列表进行排序。 - static void copy(List<? super T> dest, List<? extends T> src)
将所有元素从一个列表复制到另一个列表。 - static void fill(List<? super T> list, T obj) 使用指定元素替换指定列表中的所有元素。
- static void shuffle(List<?> list) 使用默认随机源对指定列表进行置换。
- static boolean disjoint(Collection<?> c1, Collection<?> c2)
如果两个指定 collection 中没有相同的元素,则返回 true。 - static int frequency(Collection<?> c, Object o)
返回指定 collection 中等于指定对象的元素数。 - static max()
- static min()
- static boolean replaceAll(List list, T oldVal, T newVal)
使用另一个值替换列表中出现的所有某一指定值。 - tatic void reverse(List<?> list)
反转指定列表中元素的顺序。