集合框架
早期的集合类(现在已经过时,但是Stack也是可以使用的)
1.Vector
import java.io.*;
import java.util.Vector;
public class Test {
public static void main(String[] args) throws IOException {
Vector<Integer> numbers = new Vector<>(); //向量,也可以被称作动态数组,线程安全的数组
numbers.add(1);
numbers.add(10);
numbers.add(3);
numbers.add(5);
System.out.println(numbers.get(0));
System.out.println(numbers.get(2));
System.out.println(numbers.size());
}
}
2.Stack: 后进先出
import java.io.*;
import java.util.Stack;
public class Test {
public static void main(String[] args) throws IOException {
Stack<String> stack = new Stack<>(); //后进先出
//push被称作压栈,即往栈中放内容
stack.push("abc");
stack.push("def"); stack.push("hij");
//就是看看谁在栈的最上面,但是不会就出来
System.out.println(stack.peek());
//将元素冲栈中取出
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
//压栈,弹栈,查看栈顶元素
}
}
3.Hashtable
import java.io.*;
import java.util.Hashtable;
public class Test {
public static void main(String[] args) throws IOException {
Hashtable<Integer, String> map = new Hashtable<>();
//Hashtable被称作哈希表,一个哈希表可以看作是一个数组,数组中的每个元素都是一对(键值对,前面的叫键,后面的叫值)
//键不允许重复(可以放,但是只留最后一次放的结果)
//键不允许为null
//值允许是相同的
map.put(1, "aa");
map.put(3, "cc");
map.put(2, "dd");
map.put(3, "zz");
// map.put(4, "aa");
// map.put(null, "abc");
// map.put(null, "def");
System.out.println(map);
Hashtable<String, Integer[]> scores = new Hashtable<>();
scores.put("tom", new Integer[]{50, 90, 76});
scores.put("jerry", new Integer[]{50, 90, 76});
}
}
Queue队列,并不过时,先进先出的结构。
import java.io.;
import java.util.;
public class Test {
public static void main(String[] args) throws IOException {
Queue<Integer> queue = new ArrayDeque<>(); //或者Queue<Integer> queue = new LinkedList<>();
queue.offer(8); //排队,也叫入队列
queue.offer(10);
queue.offer(1);
System.out.println(queue.peek()); //看看谁排在第一位,但是不让出队列
System.out.println(queue.poll()); //让队列开头的元素出队列
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.remove()); //remove在队列为空的时候再出队列会抛出异常,poll只会得到null
}
}
import java.io.;
import java.lang.reflect.Array;
import java.util.;
public class Test {
public static void main(String[] args) throws IOException {
int[] nums = {1,4,2,};
Arrays.sort(nums);
//Array是数组的反射类,Arrays是用来操纵数组的工具集合类。
int[] arr = (int[]) Array.newInstance(int.class, 10);
//newInstance用反射这个技术来创建一个数组, int.class表示这个数组的类型, 10表示这个数组的长度
System.out.println(Arrays.toString(arr));
}
}
LinkedList Collection集合
// Collection这个接口的特点是元素可以重复,元素无序,无下标(没有提供访问某一个元素的方式)
LinkedList<Integer> list = new LinkedList<>(); // 子类对象存入父类或父借口的变量中,多态
Collection<Integer> collection = new ArrayList<>();
collection.add(1); // add 添加
collection.add(3);
collection.add(9);
collection.add(5);
collection.add(7);
collection.forEach(System.out::print);
collection.forEach(e -> System.out.printf("%-3d", e));
System.out.println("\n" + collection.size());
System.out.println(collection.isEmpty());
System.out.println(collection.contains(100)); // 判断集合中是否包含元素100
collection.remove(100); // 删除集合中元素内容
collection.forEach(e -> System.out.printf("%-3d", e));
// collection.clear(); // clear 是将集合中的全部元素删除
collection.forEach(e -> System.out.printf("%-3d", e));
ArrayList
// List在后台的实现就是一个数组
List<String> oldList = new ArrayList<>(); // list的特点是元素有下标,可重复
oldList.add("abc"); oldList.add("xzc");
List<String> list = new ArrayList<String>(List.of("asd", "xcz", "efa", "zzz"));
System.out.println(list.get(2));
System.out.println(list.indexOf("xcz"));
list.add(2, "rrr"); // 在下标为2的位置上插入rrr,后面的元素自动往后移动
list.set(0, "123"); // set方式是把第0个元素直接替换为123
list.forEach(e -> System.out.printf("%-5s", e));
// add和set的区别,add是插入,set是覆盖
ListIterator<String> it = list.listIterator(); // Iterator 和 ListIterator 的区别是后者可以向前或者向后,前者只能向后
it.next(); it.next(); it.next();
System.out.printf("\n" + it.previous());
HashSet
// 即不能重复,也没有下标。他功能虽然不多,但是速度最快。
HashSet<String> oldSet = new HashSet<>();
oldSet.add("aaa");
oldSet.add("aaa");
oldSet.add("aaa");
oldSet.forEach(e -> System.out.printf("%-6s", e));
System.out.println();
HashSet<String> set = new HashSet<>(Set.of("aaa", "bbb", "ccc"));
set.add("xxxx");
set.forEach(e -> System.out.printf("%-6s", e));
System.out.println();
List<String> list = List.of("abc", "aaa", "abc", "aaa", "aaa");
HashSet<String> set1 = new HashSet<>(list);
set1.forEach(e -> System.out.printf("%-6s", e));
ArrayList的底层实现是数组:
因为ArrayList的底层实现是数组,所有按照下标查询某个元素的速度是非常快的,但是插入和删除的速度是非常慢的。
如果项目中的这个集合经常插入和删除就不适合ArrayList,如果经常查找,那么ArrayList就非常合适。
LinkedList的底层实现是双向链表
LinkedList按照下标查找某个元素是比较慢的,应该尽量避免。
// HashSet 是所有set实现中速度最快的
// LinkedHashSet 的特点是按照元素插入的顺序有序
// TreeSet 按照字典顺序有序
Set<String> set = new HashSet<>();
// Set<String> set = new TreeSet<>();
// Set<String> set = new LinkedHashSet<>();
set.add("aaa");
set.add("ccc");
set.add("bbb");
set.add("qqq");
set.add("eee");
set.add("rrr");
set.forEach(e -> System.out.printf("%-6s", e));
}
Map集合
// HashMap 是完全无序的
// LinkedHashMap 按照插入顺序有序
// TreeMap 按照键的顺序排序
Map<Integer, String> map = new LinkedHashMap<>();
map.put(1, "afd");
map.put(4, "zxc");
map.put(6, "zca");
map.put(3, "zef");
map.put(9, "vbx");
map.put(1, "fda");
System.out.println(map);
Set<Integer> keys = new HashSet<>(map.keySet()); // keySet 的作用是把映射中所有的键取出来,组成一个set集合
Collection<String> values = new ArrayList<>(map.values()); // values 的含义是取出map中的所有的值,组成一个set集合
// keySet和values产生了两个不可修改的集合
keys.add(12);
System.out.println(keys);
System.out.println(values);
System.out.println(map);
for (Integer key : keys)
System.out.printf("<%-1d, %-3s>\n", key, map.get(key));
keys.forEach(e -> {});
map.forEach((k, y) -> System.out.printf("<%-1d, %-3s>\n", k, y));
}
一个Map最大元素数量是2的30次方。
装填因子:默认值是0.75。
当一个HashMap中的元素数量已经超过数组长度的75%时,这个数组就要扩容。
之所以和ArrayList放满了再扩容不同的原因是:
Hashmap中元素过多容易产生冲突。
HashMap的初始大小如果不是2的整数次方,那么一定会将其变为比它大的最小的2的整数次方。
先记住每一个集合类和里面的方法作用即可。
紧接着去背一些和原理相关的结论。
去查看常用集合的部分重要源代码实现
去尝试实现所有的数据结构,比如自己写Stack,Queue,LinkedList等等