Java集合
List
1.ArrayList——默认从10开始自增插入
其中内部类的用处!
内部类Itr实现Iterarot接口;
ListIterator 继承 Itr 实现 ListIterator接口
SubList extends AbstractList<E> implements RandomAccess
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
ArrayList.SubList
//内部类访问外部类属性、方法this.modCount = ArrayList.this.modCount;ArrayList.this.elementData(offset + index);--注意:Arrays 的内部类 ArrayList 继承的是 AbstractList [没有add()方法] || 同理:Collections工具类,直接定义不可修改的ArrayList,所有更改结构:add()\remove()方法内部直接抛异常。private static class ArrayList<E> extends AbstractList只实现了:1.size()2.toArray()3.get(int)4.set(int,E)5.indexOf(Object) contains(Object)
判断是否存在当前集合内
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {//主要是防止 中间抛出异常//以及将elementData[]数组补全操作}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;Some VMs reserve some header words in an array.
2. LinkedList
Node 的定义://抽象部分,next、prev 前后链接
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
操作指针的严密逻辑:更新first、last; 注意 null 节点的存在
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}同理,linkLast(E e)
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;//在Node前插入void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}同理:在节点之后插入,
释放第一个节点,最后一个节点、任意一个节点
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
//封装的思想
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}public void addFirst(E e) {
linkFirst(e);
}//指针遍历public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}//逐渐能够操作数组等容器类public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
//数组是我的强项——多维拼接,所以大数据方面
Object[] a = c.toArray();//还是还原回数组
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}//细节问题;范围边界处理
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
LinkedList 实现了栈的功能
+push(in:E e){//方法体:通过使用addFirst(e)}+pop(){//通过使用removeFirst();}同理:也可以通过操作队尾实现。//addLast(e) && removeLast();
指针对比ArrayList数组public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}//成员属性:nextIndex 游标指示当前位置public boolean hasPrevious() {
return nextIndex > 0;
}public boolean hasNext() {
return nextIndex < size;
}//ArrayList@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}//ListIterator 部分public boolean hasPrevious() {
return cursor != 0;
}public boolean hasNext() {
return cursor != size;
}
Lisitr
共性与区别
迭代器实现
区别于:ArrayList的故障快速迭代器
fail-fast iterators:int modCount;
map
--TreeMap:有顺序: Map.Entry 接口对象!
——comparator ,构造TreeMap 传参,匿名构造
——comparable ,value对象实现 Comparable 接口
//常用操作:TreeMap treeMap = new TreeMap();
treeMap.put("1","张三,20");
treeMap.put("3","张三,20");
treeMap.put("6","张三,20");
treeMap.put("4","张三,20");
treeMap.put("5","张三,20");
treeMap.put("2","李四,20");
treeMap.forEach((key, value) -> {
System.out.println(key+":"+value);
});
for (Object entry:treeMap.entrySet()){
System.out.println(entry.toString());
}
TreeMap<String,String> treeMap1 = new TreeMap();
treeMap1.put("1","张三,20");
treeMap1.put("2","李四,20");
for (Map.Entry entry:treeMap1.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
--HashMap
System.out.println("EntrySet 遍历:");
for (HashMap.Entry entry:map.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("keySet 遍历:");
for (String s:map.keySet()){
System.out.println(s+":"+map.get(s));
}
获取hash值:(n - 1) & hash
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
equals的对象必须有相同的哈希值:因为 HashMap类做了这方面的相关操作:
final Node<K,V> removeNode(int hash, Object key, Object value,boolean matchValue, boolean movable) {//都存在这部分相同的代码:if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
node = p;}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}---========----
所以:如果key对象是一个自定义对象的时候,必须保障: hashCode() 方法 与 equals(Object obj) 方法 为 业务上的同一个对象!!
@Override
public int hashCode() {
return index;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Xuehao){
Xuehao temp = (Xuehao) obj;
if (temp.index == this.index){
return true;
}
}
return false;
}
LinkedHashMap
//LinkedHashMap 在 HashMap的基础上增加了如下内容:
//增强:保持元素的插入顺序
//head:第一个元素的引用,指向按插入顺序
//tail:最后一个元素的引用,指向按插入顺序LinkedHashMap 支持LRU算法,//LinkedHashMap 具有HashMap 的所有功能 +可保持插入顺序(遍历)
//HashMap + 双向链表
//双向链表:head、tail;after、before//LinkedHashMap是有序的 boolean accessOrder
//1. 插入顺序:每次插入元素,将元素放到双向链表的末尾
//2. 访问顺序:每次插入、获取元素,将该元素放到双向链表的末尾
Set
//数组或者实现了 Iterable接口地类可以用于 for each 语法/**Set 内部使用的是对应的Map来实现的,Map的key值即是set值,
* key值对应的值即 static new Object()
*Map中的Key值不可以重复,可以是null
HashSet(代填坑):HashSet无序的,同样的索引值取出来的值可能不一样
HashSet<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
set.add("F");
/*for (int i = 0; i < set.size(); i++) {
//HashSet无序的,同样的索引值取出来的值可能不一样
}*/
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
LinkedHashSet(代填坑):实现插入有序
LinkedHashSet linkedHashSet = new LinkedHashSet();
linkedHashSet.add("4");
linkedHashSet.add("5");
linkedHashSet.add("4");
linkedHashSet.add("5");
linkedHashSet.add("1");
linkedHashSet.add("2");
linkedHashSet.add("3");
linkedHashSet.add("1");
linkedHashSet.add("2");
linkedHashSet.add("3");
/*Iterator iterator = linkedHashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}*/
System.out.println("2".compareTo("3"));
//linkedHashSet.remove("2");
System.out.println(linkedHashSet);
Collection<String> collection = new HashSet<>();
collection.add("1");
collection.add("2");
linkedHashSet.removeAll(collection);
System.out.println(linkedHashSet);
TreeSet有序,指的是元素按照一定规则来排序,Comparator接口
/**TreeSet 有序,指它的内容--->TreeMap的key值
*TreeSet的值不能是null?
* 1. 如果构造TreeSet时,指定了 Comparator,则可以存放null
* 2. 如果未指定Comparator,add添加元素时需要调用元素对象的
* compareTo()---Comparable接口,因此不可存放null*/TreeSet<String> treeSet = new TreeSet<>();
treeSet.add("1");
treeSet.add("4");
treeSet.add("2");
treeSet.add("3");
Iterator iterator = treeSet.iterator();
System.out.println(treeSet);
while (iterator.hasNext()){
System.out.println(iterator.next());
}
treeSet.remove("2");
//treeSet.add(null);
System.out.println(treeSet);
compareTo() 方法重写
String类:
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
Queue
*Queue
* 定义:一种在队尾进行插入,队头进行删除
* 两端队列:同时在队尾、队头进行插入、删除操作
* 特点:
* 只能对队头或队尾元素进行操作,而不能对队列中间的元素进行操作
* 先进先出
* 后进后出
*接口:Queue、Deque
*实现类:
* 1. LinkedList 具有队列、两端队列功能,内部使用链表实现
* 2. ArrayDeque 具有队列、两端队列功能,内部使用循环数组实现
* 3. PriorityQueue 优先级队列,内部实现结构(栈)可以快速把所有元素中最小的元素单独放出来
* 最典型的应用场景:任务调度
* 应用场景:任务调度、LRU
LinkedList---实现Deque接口
Queue接口
add(E) && offer(E)
---内容限制,有限使用offer(E)
element() && peek() [retrive the head]
---队列为空,element() 抛异常;peek() 返回null
remove() && poll() [retrive the head and remove]
---队列为空,element() 抛异常;peek() 返回null
Deque接口(Douoble ended queue):insert, remove, and examine the element
每种方法两种表现形式:one throws an exception if the operation fails,the other returns a special value (either {@code null} or {@code false}, depending on the operation).参考JDK:
<table BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of Deque methods</caption>
* <tr>
* <td></td>
* <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
* <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
* </tr>
* <tr>
* <td></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Special value</em></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Special value</em></td>
* </tr>
* <tr>
* <td><b>Insert</b></td>
* <td>{@link Deque#addFirst addFirst(e)}</td>
* <td>{@link Deque#offerFirst offerFirst(e)}</td>
* <td>{@link Deque#addLast addLast(e)}</td>
* <td>{@link Deque#offerLast offerLast(e)}</td>
* </tr>
* <tr>
* <td><b>Remove</b></td>
* <td>{@link Deque#removeFirst removeFirst()}</td>
* <td>{@link Deque#pollFirst pollFirst()}</td>
* <td>{@link Deque#removeLast removeLast()}</td>
* <td>{@link Deque#pollLast pollLast()}</td>
* </tr>
* <tr>
* <td><b>Examine</b></td>
* <td>{@link Deque#getFirst getFirst()}</td>
* <td>{@link Deque#peekFirst peekFirst()}</td>
* <td>{@link Deque#getLast getLast()}</td>
* <td>{@link Deque#peekLast peekLast()}</td>
* </tr>
* </table>
自定义简单实现应用:ArraySequence—& —内部类
//接口定义public interface IndexPrint {
public boolean end();
public Object current();
public void next();
}//封装正向访问、逆向访问类public class ArraySequence implements IndexPrint{
private int count = 0;
private Object[] data;
public ArraySequence(int size){
this.data = new Object[size];
}
public Verse pro(){
return new Verse();
}
public Reverse pro1(){
return new Reverse();
}
public void add(Object object){
if(count<data.length){
data[count++] = object;
//reverseIndex++;
}
}
@Override
public boolean end(){
return count==data.length;
}
@Override
public Object current() {
return null;
}
@Override
public void next() {
}
class Verse implements IndexPrint{
private int index = 0;
@Override
public boolean end() {
return index>=count;
}
@Override
public Object current() {
if(index<count){
return data[index];
}
return null;
}
@Override
public void next() {
index++;
}
}
class Reverse implements IndexPrint{
private int reverseIndex=count;
@Override
public boolean end() {
return (reverseIndex-1) <0;
}
@Override
public Object current() {
if((reverseIndex-1)<count){
return data[reverseIndex-1];
}
return null;
}
@Override
public void next() {
reverseIndex--;
}
}
public void print(){
System.out.println(Arrays.toString(data));
}
}
优先级队列应用
static class Task implements Comparable{
private int priority;
private String name;
public Task(int priority,String name){
this.priority = priority;
this.name = name;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Object o) {
if(o instanceof Task){
if(this.priority<((Task) o).priority){
return -1;
}
if(this.priority>((Task) o).priority){
return 1;
}
}
return 0;
}
@Override
public String toString() {
return this.name+":"+this.priority;
}
}
static void taskManage(){
PriorityQueue<Task> priorityQueue = new PriorityQueue<>(new Comparator<Task>() {
@Override
public int compare(Task o1, Task o2) {
if(o1.getPriority()<o2.getPriority()){
return -1;
}
if(o1.getPriority()>o2.getPriority()){
return 1;
}
return 0;
}
});
//priorityQueue.add(new())
int i=0;
while ((i)<10){
int priority = new Random().nextInt(10);
priorityQueue.add(new Task(priority,"任务"+i));
i++;
}
System.out.println(priorityQueue);
while (!priorityQueue.isEmpty()){
System.out.println(priorityQueue.remove());
}
}
从Java集合类中看到内部类的重要性!
老师说的不重要性:或许仅限于,Java网页开发??
Java集合类学习泛型应用
1:LinkedList 内部类 Node定义
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
2:LinkedList插入元素:安全性意识
不改变元素的值:final修饰,安全性!
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
泛型方法
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
快速查询第index处的node节点
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
从输出结果:也能看出Java面向对象的思想!Integer[] numb = new Integer[2];
System.out.println(numb);//输出数组名@hash地址
Integer[] numb1 = {};
System.out.println(numb1);
numb1 = null;
System.out.println(numb1);//null
最终比拼的是:
业务能力
跟实际业务的关联关系捋清楚
人际成单招标能力
//StringBuffer \ StringBuilder 操作字符串
public String toString() {
//return name+":"+age;
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append("{");
sb.append(name);
sb.append(",");
sb.append(age);
sb.append("}");
return sb.toString();
}//转义符的应用
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
注解应用:@SuppressWarnings("unchecked") E e = (E) o;多变量赋值:int a,b;
a = b = true?1:3;
区分
StringBuffer && StringBuilder
---默认长度 16