数组
数组的拷贝
/** * 删除数组中指定索引位置的元素,本质上还是数组的拷贝 * * @param s * @param index * @return */ public static String[] removeElement(String[] s, int index) { System.arraycopy(s, index + 1, s, index, s.length - index - 1); s[s.length - 1] = null; return s; }
/** * 数组扩容,本质上是定义一个更大的数组,然后将原数组内容拷贝到新数组中 * * @param s * @param num * @return */ public static String[] extendRange(String s, int num) { String[] s1 = new String[s.length() + num]; System.arraycopy(s, 0, s1, 0, s.length()); return s1; }
java.util.Arrays
- Array.toString() //打印数组
- Array.binarySearch() //二分法查找数组元素
多维数组
冒泡排序
/** * 冒泡排序法 * * @param a * @return */ public static void bubbleSort(int[] a) { int temp; for (int j = 0; j < a.length - 1; j++) { //flag判断是否执行了交换 boolean flag = true; for (int i = 0; i < a.length - j - 1; i++) { if (a[i] < a[i + 1]) { temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; flag = false; } System.out.println(Arrays.toString(a)); } if (flag) { break; } } }
二分法查找
/** * 二分法查找 * * @param a * @param value * @return */ public static int binarySearch(int[] a, int value) { Arrays.sort(a); int low = 0; int high = a.length - 1; while (low < high) { int mid = (low + high) / 2; if (value == a[mid]) { return mid; } if (value < a[mid]) { high = mid - 1; } if (value > a[mid]) { low = high + 1; } } return -1; }
异常
容器(集合)
- 数组也是一种容器
- 数组的效率高
- 数组不够灵活
[容器接口层次结构图]](https://img2018.cnblogs.com/blog/1121560/201912/1121560-20191203075856847-1936133502.png)
泛型
- 建立类型安全的集合
- 本质是数据类型的参数化
Collection接口常用方法
Collection<String> c = new ArrayList<>(); //return the number of elements in this collection c.size(); //return True if this collection contains no elements c.isEmpty(); c.add(); //**removes** a single instance of the specified element from this collection c.remove(); //**removes** all of the elements from this collection c.clear(); //return an array containing all of the elements in this collection. Object[] objs = c.toArray(); Collection<String> c2 = new ArrayList<>(); //Returns true if this collection contains all of the elements in the specified collection. c.containAll(c2); //Adds all of the elements in the specified collection to this collection (optional operation). c.addAll(c2); //Removes all of this collection's elements that are also contained in the specified collection (optional operation). c.removeAll(c2);
List
有序可重复
常用实现类:ArrayList (数组),LinkedList(链表),Vector(数组)
常用方法:
List<String> list = new List<>(); list.add(0,"a"); list.remove(0); list.set(0,"b"); list.get(0); //Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index. list.indexOf("a"); //Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the highest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index. list.lastIndexOf("a");
ArrayList
- ArrayList底层使用数组实现的存储
- 查询效率高,线程不安全,使用较多
- 底层实现:
/** * 自定义实现ArrayList,体会底层原理 * <p> * 泛型 * 数组扩容 * set/get方法 * 数组边界的检查 * remove * * @author lance */ public class NewArrayList<E> { private Object[] elementData; private int size; private static final int DEFAULT_CAPACITY = 10; public NewArrayList() { elementData = new Object[DEFAULT_CAPACITY]; } public NewArrayList(int capacity) { if (capacity < 0) { throw new RuntimeException(""); } else if (capacity == 0) { elementData = new Object[DEFAULT_CAPACITY]; } else { elementData = new Object[capacity]; } } public void add(E element) { //扩容 if (size == elementData.length) { //10-->10+10/2 Object[] newArray = new Object[elementData.length + (elementData.length >> 1)]; System.arraycopy(elementData, 0, newArray, 0, elementData.length); elementData = newArray; } elementData[size++] = element; } public E get(int index) { checkRange(index); return (E) elementData[index]; } public void set(E element, int index) { checkRange(index); elementData[index] = element; } public void remove(E element) { //将element和所有元素挨个比较,获得第一个比较为true的,返回 for (int i = 0; i < size; i++) { if (element.equals(get(i))) { remove(i); } } } public void remove(int index) { int numMoved = elementData.length - index - 1; if (numMoved > 0) { System.arraycopy(elementData, index + 1, elementData, index, numMoved); } elementData[--size] = null; } public void checkRange(int index) { if (index < 0 || index > size - 1) { throw new RuntimeException("index is illegal" + index); } } public int size() { return size; } public boolean isEmpty() { return size == 0 ? true : false; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < size; i++) { sb.append(elementData[i] + ","); } sb.setCharAt(sb.length() - 1, ']'); return sb.toString(); } }
LinkedList
查询效率低,增删效率高
底层实现:
public class Node { /** * previous:上一个节点 * next:下一个节点 * element:数据 */ Node previous; Node next; Object element; public Node(Node previous, Node next, Object element) { this.previous = previous; this.next = next; this.element = element; } public Node(Object element) { this.element = element; } } /** * 自定义链表 * <p> * get() * remove() * add() * * @param <E> */ public class NewLinkedList<E> { private Node first; private Node last; private int size; public void add(E element) { Node node = new Node(element); if (first == null) { //node.previous = null; //node.next = null; first = node; last = node; } else { node.previous = last; node.next = null; last.next = node; last = node; } size++; } public E get(int index) { checkRange(index); Node temp = getNode(index); return temp != null ? (E) temp.element : null; } public void remove(int index) { checkRange(index); Node temp = getNode(index); if (temp != null) { Node up = temp.previous; Node down = temp.next; if (up != null) { up.next = down; } if (down != null) { down.previous = up; } if (index == 0) { first = down; } if (index == size - 1) { last = up; } size--; } } public void add(int index, E element) { Node newNode = new Node(element); Node temp = getNode(index); if (temp != null) { Node up = temp.previous; up.next = newNode; newNode.previous = up; newNode.next = temp; temp.previous = newNode; } } private Node getNode(int index) { checkRange(index); Node temp = null; //size/2 if (index <= (size >> 1)) { temp = first; for (int i = 0; i < index; i++) { temp = temp.next; } } else { temp = last; for (int i = size - 1; i > index; i--) { temp = temp.previous; } } return temp; } private void checkRange(int index) { if (index < 0 || index > size - 1) { throw new RuntimeException("索引不合法" + index); } } @Override public String toString() { StringBuilder sb = new StringBuilder("["); Node temp = first; while (temp != null) { sb.append(temp.element + ","); temp = temp.next; } sb.setCharAt(sb.length() - 1, ']'); return sb.toString(); } }
Vector
- 线程安全,效率低
Map
Key-value方式存储,key不能重复(equals)
实现类:HashMap,TreeMap,HashTable,Properties
常用方法:
Map<Integer,String> m1 = new HashMap<>(); //Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value. (A map m is said to contain a mapping for a key k if and only if m.containsKey(k) would return true.) m1.put(1,"one"); //Returns the number of key-value mappings in this map. m1.size(); //Returns true if this map contains no key-value mappings. m1.isEmpty(); //Returns true if this map contains a mapping for the specified key. More formally, returns true if and only if this map contains a mapping for a key k such that (key==null ? k==null : key.equals(k)). (There can be at most one such mapping.) m1.containsKey(1); //Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that (value==null ? v==null : value.equals(v)). This operation will probably require time linear in the map size for most implementations of the Map interface. m1.containsValue("one"); Map<Integer,String> m2 = new HashMap<>(); m1.put(2,"two"); //Copies all of the mappings from the specified map to this map (optional operation). The effect of this call is equivalent to that of calling put(k, v) on this map once for each mapping from key k to value v in the specified map. The behavior of this operation is undefined if the specified map is modified while the operation is in progress. m1.putAll(m2);
Hashmap
- HashMap底层实现采用了哈希表
- 哈希表本质是“数组”+“链表”
- 数组:占用空间连续,查询快,增删慢
- 链表:占用空间不连续,查询慢,增删快
- 线程不安全,效率高
底层实现:
/** * 自定义HashMap * <p> * toString() * put() * get() * * @author lance */ public class NewHashMap<K, V> { /** * 位桶数组 */ Node2[] table; /** * 存放键值对的个数 */ int size; public NewHashMap() { table = new Node2[16]; } /** * newNode 定义新的节点对象 * iterLast 正在遍历的最后一个元素 * keyRepeat 如果没有发生key重读的情况,则添加到链表最后 * * @param key * @param value */ public void put(K key, V value) { Node2 newNode = new Node2(); newNode.hash = myHash(key.hashCode(), table.length); newNode.key = key; newNode.value = value; newNode.next = null; Node2 temp = table[newNode.hash]; Node2 iterLast = null; boolean keyRepeat = false; if (temp == null) { table[newNode.hash] = newNode; size++; } else { while (temp != null) { if (temp.key.equals(key)) { keyRepeat = true; temp.value = value; break; } else { iterLast = temp; temp = temp.next; } } if (!keyRepeat) { iterLast.next = newNode; size++; } } } public K get(K key) { int hash = myHash(key.hashCode(), table.length); Object value = null; if (table[hash] != null) { Node2 temp = table[hash]; while (temp != null) { if (temp.key.equals(key)) { value = temp.value; break; } else { temp = temp.next; } } } return (K) value; } /** * 自定义Hash算法 * * @param v * @param length * @return */ public int myHash(int v, int length) { //位运算的效率高 return v & (length - 1); } @Override public String toString() { StringBuilder sb = new StringBuilder("{"); //遍历位桶数组 for (int i = 0; i < table.length; i++) { Node2 temp = table[i]; //遍历链表 while (temp != null) { sb.append(temp.key + ":" + temp.value + ","); temp = temp.next; } } sb.setCharAt(sb.length() - 1, '}'); return sb.toString(); } }
TreeMap
一般用于排序
是红黑二叉树的典型实现
import java.util.Map; import java.util.TreeMap; /** * 测试TreeMap * 按照key递增的方式排序 * 测试Comparable接口实现自定义排序 * * @author lance */ public class NewTreeMap { public static void main(String[] args) { Map<Integer, String> tm = new TreeMap<>(); tm.put(20, "a"); tm.put(2, "b"); tm.put(21, "c"); //按照key递增的方式排序 for (Integer key : tm.keySet()) { System.out.println(key + "---" + tm.get(key)); } Map<Emp, String> tm2 = new TreeMap<>(); tm2.put(new Emp(1, "Tom", 10000), "good"); tm2.put(new Emp(2, "Cat", 20000), "nice"); tm2.put(new Emp(3, "Lance", 30000), "excellent"); for (Emp key : tm2.keySet()) { System.out.println(key + "---" + tm2.get(key)); } } } class Emp implements Comparable<Emp> { int id; String name; double salary; public Emp(int id, String name, double salary) { this.id = id; this.name = name; this.salary = salary; } @Override public String toString() { return "id: " + id + " name: " + name + " salary: " + salary; } @Override public int compareTo(Emp o) { if (this.salary > o.salary) { return 1; } else if (this.salary < o.salary) { return -1; } else { if (this.id > o.id) { return 1; } else if (this.id < o.id) { return -1; } else { return 0; } } } }
HashTable
- HashMap线程不安全,效率高,允许key或value为null
- HashTable线程安全,效率低,不允许key或value为null
Set
- 没有顺序不可重复
- 常用实现类:HashSet,TreeSet
- 继承Collection接口
HashSet
底层实现
import java.util.HashMap; /** * 手动实现HashSet * add() * size() * * @author lance */ public class NewHashSet { HashMap map; private static final Object PRESENT = new Object(); public NewHashSet() { map = new HashMap(); } public void add(Object o) { map.put(o, PRESENT); } public int size() { return map.size(); } @Override public String toString() { StringBuilder sb = new StringBuilder("["); for (Object key : map.keySet()) { sb.append(key + ","); } sb.setCharAt(sb.length() - 1, ']'); return sb.toString(); } }
TreeSet
迭代器
/** * 迭代器遍历List */ public static void IteratorList() { List<String> list = new ArrayList<>(); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String temp = iter.next(); System.out.println(temp); } } /** * 迭代器遍历Set */ public static void IteratorSet() { Set<String> set = new HashSet<>(); for (Iterator<String> iter = set.iterator(); iter.hasNext(); ) { String temp = iter.next(); System.out.println(temp); } } /** * 迭代器遍历Map */ public static void IteratorMap() { Map<String, String> map = new HashMap<>(); Set<Map.Entry<String, String>> ss = map.entrySet(); for (Iterator<Map.Entry<String, String>> iter = ss.iterator(); iter.hasNext(); ) { Map.Entry<String, String> temp = iter.next(); System.out.println(temp.getKey() + temp.getValue()); } } /** * 迭代器遍历Map */ public static void IteratorMap2() { Map<String, String> map = new HashMap<>(); Set<String> keySet = map.keySet(); for (Iterator<String> iter = keySet.iterator(); iter.hasNext(); ) { String key = iter.next(); System.out.println(key + "---" + map.get(key)); } }
Collections 工具类
public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key) Searches the specified list for the specified object using the binary search algorithm. The list must be sorted into ascending order according to the natural ordering of its elements (as by the sort(List) method) prior to making this call. If it is not sorted, the results are undefined. If the list contains multiple elements equal to the specified object, there is no guarantee which one will be found. public static void reverse(List<?> list) Reverses the order of the elements in the specified list. public static void shuffle(List<?> list) Randomly permutes the specified list using a default source of randomness. All permutations occur with approximately equal likelihood.
Orm
import java.util.*; /** * 使用容器存储表格数据(orm对象关系映射) * <p> * 每一行使用Map * 整个表格使用List * * @author lance */ public class Orm01 { public static void main(String[] args) { Map<String, Object> row1 = new HashMap<>(); row1.put("id", 1001); row1.put("name", "Tom"); row1.put("salary", 10000); Map<String, Object> row2 = new HashMap<>(); row2.put("id", 1002); row2.put("name", "Cat"); row2.put("salary", 12000); Map<String, Object> row3 = new HashMap<>(); row3.put("id", 1003); row3.put("name", "Kate"); row3.put("salary", 15000); List<Map<String, Object>> table1 = new ArrayList<>(); table1.add(row1); table1.add(row2); table1.add(row3); for (Map<String, Object> row : table1) { Set<String> keySet = row.keySet(); for (String key : keySet) { System.out.print(key + ":" + row.get(key) + "\t"); } System.out.println(); } } }