一.List接口
1.特点
- 有序
- 有索引
- 可重复,元素可为null
- 底层用数组实现
2. ArrayList
2.1 实现
public class MyArrayList {
private Object[] objects = null;
private final int DEFAULT_LENGTH = 10;
private int length;
private int size= 0;
private final int LOAD = 2;
public MyArray() {
length = DEFAULT_LENGTH;
objects = new Object[length];
}
public MyArray(int length) {
this.length = length;
objects = new Object[length];
}
public void add(Object o) {
if(size==length) {
length = length*LOAD;
objects = Arrays.copyOf(objects,length);
}
objects[size]=o;
size++;
}
public void add(int index,Object o) {
if(index<0||index>size-1) {
throw new ArrayIndexOutOfBoundsException("访问越界");
}else {
if(size==length) {
length = length*LOAD;
objects = Arrays.copyOf(objects,length );
}
System.arraycopy(objects, index, objects, index+1, size-index);
objects[index] = o;
size++;
}
}
public void remove(int index) {
if(index<0||index>size-1) {
throw new ArrayIndexOutOfBoundsException("访问越界");
}else {
objects[index]= null;
System.arraycopy(objects, index+1, objects,index , size-index);
size--;
}
}
public int indexOf(Object o) {
if(o==null) {
return -1;
}
for (int i = 0; i < size; i++) {
Object object = objects[i];
if(o.equals(object)) {
return i;
}
}
return -1;
}
public boolean contains(Object o) {
int i = indexOf(o);
return i>=0?true:false;
}
public void removeAll() {
Arrays.fill(objects, null);
size =0;
}
public void update(int index,Object o) {
if(index<0||index>size-1) {
throw new ArrayIndexOutOfBoundsException("访问越界");
}
objects[index] = o;
}
public Object get(int index) {
if(index<0||index>size-1) {
throw new ArrayIndexOutOfBoundsException("访问越界");
}
return objects[index];
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer("[");
for (int i = 0; i < size; i++) {
sb.append(objects[i]);
sb.append(",");
}
sb.append("]");
return sb.toString().replace(",]", "]");
}
public int size() {
return size;
}
}
2.2 方法
方法 | 描述 |
---|
add(Object o) | 添加数据 |
add(int index,Object o) | 在制定索引处添加元素 |
size() | 获取元素个数 |
get(int index) | 获取索引处的元素 |
isEmpty() | 判断集合是否为空 |
indexOf(Object o) | 判断某个元素第一次出现的位置 |
E remove(int index) | 移除索引处元素,并返回该元素 |
boolean remove(Object o) | 移除元素 |
clear() | 清空元素 |
set(int index ,E e) | 修改索引处的元素 |
iterator() | 获取迭代器 |
trimToSize() | 减少容量指当前元素个数 |
contains(Object o) | 判断是否包含某个元素 |
lastIndexOf(Object o) | 判断某个元素最后一次出现的位置 |
toArray() | 将集合转换为数组 |
addAll(Collection<? extends E> c) | 集合中添加集合 |
addAll(int index, Collection<? extends E> c) | 索引处添加集合 |
retainAll(Collection c) | 求两个集合的交集 |
removeAll(Collection<?> c) | 移除传入集合内的元素 |
subList(int fromIndex, int toIndex) | 获取子集合 |
2.3List遍历
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(4);
list.add(2);
for (Integer integer : list) {
System.out.println(integer);
}
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
int i = it.next();
System.out.println(i);
}
}
3.LinkedList
3.1双向链表实现
public class MyLinkedList<E>{
private int size;
private Node first;
private Node last;
public MyLinkedList() {
first = null;
last = null;
size = 0;
}
private void linkLast(E e) {
if(first==null||last==null||size==0) {
Node<E> newNode = new Node(null,e,null);
first = newNode;
last = newNode;
}else {
Node<E> newNode = new Node(last,e,null);
last.next = newNode;
last = newNode;
}
size++;
}
private void linkFirst(E e) {
if(first==null) {
Node<E> newNode = new Node<E>(null, e, null);
first = newNode;
last = newNode;
}else {
Node<E> newNode = new Node<E>(null, e, first);
first.pre = newNode;
first = newNode;
}
size++;
}
private void linkBefore(int index,E e) {
chcekRange(index);
Node<E> node = new Node(null,e,null);
Node<E> indexNode = getNodeByIndex(index);
Node<E> pre = indexNode.pre;
node.pre = pre;
pre.next = node;
node.next = indexNode;
indexNode.pre=node;
size++;
}
private void linkAfter(int index,E e) {
chcekRange(index);
Node<E> indexNode = getNodeByIndex(index);
Node<E> next = indexNode.next;
Node<E> newNode = new Node(indexNode,e,next);
indexNode.next = newNode;
next.pre = newNode;
size++;
}
public void add(E e) {
linkLast(e);
}
public void add(int index,E e) {
linkAfter(index, e);
}
public boolean remove(int index) {
chcekRange(index);
if(index==0) {
Node<E> removeNode = first;
first = first.next;
first.pre = null;
removeNode.next=null;
}else if(index==size-1) {
Node<E> removeNode = last;
last = last.pre;
last.next = null;
removeNode.pre = null;
}else {
Node<E> indexNode = getNodeByIndex(index);
Node<E> next = indexNode.next;
Node<E> pre = indexNode.pre;
pre.next = next;
next.pre = pre;
}
size--;
return true;
}
public E get(int index) {
chcekRange(index);
Node<E> node = getNodeByIndex(index);
return node.data;
}
public void set(int index,E e) {
chcekRange(index);
Node<E> current = first;
for (int i = 0; i < size&¤t!=null;i++,current = current.next) {
if(i==index) {
current.data = e;
}
}
}
public void clear() {
first =null;
last =null;
size=0;
}
public boolean isEmpty() {
return size==0;
}
private Node<E> getNodeByIndex(int index){
if(index<0||index>size) {
throw new IndexOutOfBoundsException("访问越界");
}
if(index==0) {
return first;
}else if(index==size-1) {
return last;
}else {
Node<E> current = first;
for (int i = 0; i < size&¤t!=null; i++) {
if(i==index) {
return current;
}
current = current.next;
}
}
return first;
}
public void chcekRange(int index) {
if(index<0||index>size-1) {
throw new IndexOutOfBoundsException("访问越界");
}
}
@Override
public String toString() {
if(size==0) {
return "[]";
}
Node<E> current = first;
StringBuffer sb =new StringBuffer("[");
for (int i = 0; i < size&¤t!=null; i++,current=current.next) {
sb.append(current.data);
if(i!=size-1) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
class Node<E>{
Node<E> pre;
E data;
Node<E> next;
public Node(Node<E> pre, E data, Node<E> next) {
super();
this.pre = pre;
this.data = data;
this.next = next;
}
}
}
3.2 方法
方法 | 描述 |
---|
add(Object o) | 添加数据 |
add(int index,Object o) | 在指定索引处添加元素 |
size() | 获取元素个数 |
get(int index) | 获取索引处的元素 |
isEmpty() | 判断集合是否为空 |
indexOf(Object o) | 判断某个元素第一次出现的位置 |
E remove(int index) | 移除索引处元素,并返回该元素 |
boolean remove(Object o) | 移除元素 |
clear() | 清空元素 |
set(int index ,E e) | 修改索引处的元素 |
addFirst(E e) | 链表首部添加元素 |
addLast(E e) | 链表末尾添加元素 |
removeFirst() | 移除首节点 |
removeLast() | 移除尾节点 |
getFirst() | 获取第一个节点 |
getLast() | 获取最后一个几点 |
二.Set接口
1.特点
- 无序
- 无索引
- 不可重复
2.HashSet
2.1方法
方法 | 描述 |
---|
add(Object o) | 添加元素 |
remove(Object o) | 移除元素 |
isEmpty() | 判断元素是否为空 |
2.2.HashSet遍历
public class Test {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("陈忠实");
set.add("贾平凹");
set.add("路遥");
set.add("张爱玲");
set.add("林徽因");
boolean a = set.add("徐志摩");
System.out.println(a);
boolean b = set.add("徐志摩");
System.out.println(b);
for (String s : set) {
System.out.println(s);
}
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
2.3重写hashCode规则
- 同一对象多次调用hashCode()方法时,返回值应该相同
- equals()方法返回值为true时,hashCode应该相同
- 所有参与equals方法的成员变量,都应该参与hashCode计算(为防止偶然和相等,造成hash冲突,应该用每个成员变量乘以一个质数)
3.TreeSet
三.Map接口
1.HashMap
1.1方法
方法 | 描述 |
---|
put(K key,V value) | 添加键值对 |
get(Object key) | 根据键获取值 |
keySet() | 获取keySet |
entrySet() | 获取entrySet |
containsKey(Object key) | 判断是否存在key |
remove(Object key) | 根据key删除键值对 |
remover(Object key,Object value) | 根据key和value删除键值对 |
size() | 获取元素个数 |
isEmpty() | 判断map是否为空 |
1.2HashMap遍历
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("乔峰",30);
map.put("虚竹", 20);
map.put("李秋水", 20);
map.put("天山童姥", 60);
map.put("梦姑",18);
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
int i = map.get(key);
System.out.println("key==========="+key);
System.out.println("value========="+i);
}
}
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("乔峰",30);
map.put("虚竹", 20);
map.put("李秋水", 20);
map.put("天山童姥", 60);
map.put("梦姑",18);
Set<Entry<String, Integer>> set = map.entrySet();
for (Entry<String, Integer> entry : set) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println("key=========="+key);
System.out.pintln("key=========="+value);
}
}
1.3HashMap和Hashtable的 区别
-
HashMap和Hashtable都是Map接口的子类
-
HashMap的key和value都可以为null,只能存入一个为null的key,Hashtable的key和value都不能为null
-
HashMap非线程安全,Hashtable线程安全
2.TreeMap
四.面试题
- ArrayList,Vector,LinkedList的区别
- ArrayList,Vector底层实现是数组,LinkedList底层实现是双向链表
- Vector线程安全,ArrayList,LinkedList非线程安全
- ArrayList,Vector查找快,增删慢,LinkedList增删快,查找慢
- ArrayList,Vector,LinkedList都是List接口的实现类
- ArrayList,Vector,LinkedList都有序,有索引,可重复。