集合的概念和作用
集合就是将多个元素包含在一起,通过集合可以对这些元素进行管理和使用。
集合和数组的区别
- 集合是面对对象的,不能存储基本数据类型,需要对基本数据进行包装。
- 集合中往往实现了大量的方法,可以实现对元素的各种操作。
- 数组实现简单,效率高。
- java中的集合有多种实现,包括数组存储数据、链表存储数据、有序存储、无序存储等等。
- 数组的容量是固定的,而集合容量可以动态扩展。
集合框架体系介绍
Collection:单元素集合的接口。
Map:键值对映射集合的接口。
Iterator:迭代器,用于遍历集合。
Collections:工具类,大量处理集合的静态方法。
Comparable:用于排序
集合框架之Collection接口
Collection接口是单个元素集合的接口。实现了Iterator接口,声明了单个元素集合所具有的方法。
泛型的使用
泛型是为了提高泛用性而出现的。在java中有泛型类、泛型方法、泛型变量。
以泛型类为例,在实现类时可以不指定特定的类型,在创建对象时再指定类的泛型类型。使用泛型可以让一个类接收多种类型的数据,ArrayList就是一个泛型类,它既可以是Integer类型的集合,也可以是String类型的集合,当然也可以是其他引用类型的集合。
ArrayList和LinkedList的方法使用
ArrayList部分方法使用,LinkedList的方法功能大致和Arraylist相同,但是在实现上有不同,这和LinkedList的结构为链表有关。
package com.peng.selling.coding;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Father {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("bss");
list.add("sss");
list.add("c");
System.out.println("集合第一个元素:"+list.get(0));
System.out.println("集合的大小:"+list.size());
System.out.println("a的索引:"+list.indexOf("a"));
System.out.println("是否包含b:"+list.contains("b"));
list.sort(Comparator.comparing(String::length).reversed());
System.out.println("按字符串长度降序排序:"+list);
list.sort((String s1,String s2)->{
if(s1.charAt(0)>s2.charAt(0)){
return 1;
}else{
return -1;
}
});
System.out.println("按字符串首字符升序排序:"+list);
list.remove("a");
System.out.println("移除字符串a后:"+list);
}
}
结果:
ArrayList和LinkedList各自的工作原理分析原理分析
ArrayList实现 List 接口、底层使用数组保存所有元素。ArrayList初始容量大小为10,当超过容量后,会进行扩容,以原来容量的1.5倍来扩容。
LinkedList实现 List 接口、底层使用链表保存所有元素。链表不用进行扩容,每一个节点都一个前驱和后继节点。还实现了Deque接口,它还是一个队列,可以被当成双端队列来使用。
由于List接口实现了Collection接口,Collection接口又实现了Iterator接口,所以两者都可以使用Iterator来遍历。
Vector和Stack使用介绍
Vector功能大致和ArrayList相似,但Vector是一个线程安全的数组。Vector中所有操作数组的方法都加上了synchronize关键字。
Stack是Vector子类,Stack是一个栈,除了继承Vector方法之外还添加了一些栈独有的方法。
- empty():判断栈是否为空栈。
- peek():查看栈顶部的对象,但不从栈中移除它。
- push():压栈,将元素加入栈顶。
- pop():弹栈,获得栈顶的元素。
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack);
System.out.println(stack.peek());
stack.pop();
System.out.println(stack);
}
[1, 2, 3]
3
[1, 2]
使用多种方式遍历集合
- 1、使用普通for循环
- 2、使用增强for循环(foreach)
- 3、使用iterator迭代器
在使用foreach和iterator遍历集合时不能增加或者删除元素
源码中的备注
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
for (String s : list) {
System.out.println(s);
}
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
迭代器的使用和工作原理
Collection接口实现了iterator接口,因此List,Set,Queue都可以使用迭代器遍历元素。
iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素。在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,每调用一次迭代器的next方法,迭代器的索引会向后移动一位,并将指向的元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
迭代器的重要方法如下:
- remove():移除迭代器所在位置的元素。
- hasNext():判断数组是否还有元素。
- next():获得迭代器下一个元素,指针向后移动一位。
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
HashSet和LinkedHashSet各自的工作原理分析
首先HashSet实现了Set接口,Set接口实现了Collection接口。
HashSet是一个无重复元素的无序数组,底层是hash表。HashSet的内部其实是一个HashMap对象,对HashSet对象添加元素或者删除元素都是调用的HashMap的方法
LinkedHashSet是HashSet的子类,在HashSet的基础上,加上了链表,因此它是有序的。LinkedHashSet的构造方法的底层实现还是在LinkedHashMap中的。用给定的容量和填充因子构造一个空链接散列集。
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
集合框架之Map接口
Map是键值对映射的集合。每个元素具有key和value两个属性,key是唯一的。
提供了key就可以通过key找到value。
TreeMap的方法使用和排序方式
TreeMap的常用方法有:
- put(key,value):添加一堆键值对
- get(key):通过key获得value
- conatinsKey():判断是否包含key
- containsValue():判断是否包含value
- clear():清空map
- keySet():获得key的集合
- entrySet():获得映射关系的集合
排序方式:TreeMap按照key的字典顺序来排序,对于字符串类型,会比较首字母的ASCII码,对于Integer类型会比较大小。
package com.peng.selling.coding;
import java.util.*;
public class Father {
public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("Mike",20);
map.put("Cindy",19);
map.put("John",25);
System.out.println(map.get("Mike"));
for(String key:map.keySet()){
System.out.println(key+" : "+map.get(key));
}
for (Integer value : map.values()) {
System.out.println(value);
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
}
分析Set和Map之间的区别与联系
1、Map是键值对,Set是值的集合。
2、Set是无法获取到某一特定的值的,只能遍历判断其是否存在,Map可以通过key获得value。
3、两者都不存放重复的元素。
4、两者都实现了Iterator接口
Collections工具类的使用
- 工厂方法
- collections工具类里面有生产线程安全的对象synchronizedList、synchronizedMap、synchronizeSet的工厂方法。
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList<String>());
Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());
Set<String> set = Collections.synchronizedSet(new HashSet<String>());
}
- 排序方法
Collections中有默认的升序降序排序方法,也可以通过Comparator的静态方法的规则来排序,也可以自定义规则排序。
package com.peng.selling.coding;
import java.util.*;
public class Father {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aa");
list.add("css");
list.add("coc");
list.add("b");
Collections.sort(list);
System.out.println("首字母升序:"+list);
Collections.reverse(list);
System.out.println("首字母降序:"+list);
Collections.sort(list,Comparator.comparing(String::length));
System.out.println("字符串长度:"+list);
//自定义规则排序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
if(s1.charAt(s1.length()-1)>s2.charAt(s2.length()-1)){
return 1;
}else{
return -1;
}
}
});
System.out.println("末末尾字母升序:"+list);
}
}
- 查找方法
Collections.min():查找最小值
Collections.max():查找最大值
Collections.frequency():查找元素出现的次数
Collections.shuffle():打乱集合
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(1);
list.add(2);
list.add(3);
System.out.println("集合中最大数字:"+Collections.min(list));
System.out.println("集合中最小数字:"+Collections.max(list));
System.out.println("集合中1出现的次数:"+Collections.frequency(list,1));
Collections.shuffle(list);
System.out.println(list);
}