一.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
- TreeSet内添加对象的类必须实现Comparable接口并重写compareTo方法
- TreeSet通过compareTo方法判断两个对象是否相等
- 如果equals方法返回true,compareTo方法应该返回0
三.Map接口
1.HashMap
1.1方法
方法 |
描述 |
put(K key,V value) |
添加键值对 |
get(Object key) |
根据键获取值 |
keySet() |
获取keySet |
entrySet() |
获取entrySet |
clear() |
清空 |
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线程安全
- HashMap数组初始长度为16,Hashtable初始长度为11
2.TreeMap
- key有序
- key必须实现Comparable接口,并重写comparableTo方法
四.面试题
-
ArrayList,Vector,LinkedList的区别
- ArrayList,Vector底层实现是数组,LinkedList底层实现是双向链表
- Vector线程安全,ArrayList,LinkedList非线程安全
- ArrayList,Vector查找快,增删慢,LinkedList增删快,查找慢
- ArrayList,Vector,LinkedList都是List接口的实现类
- ArrayList,Vector,LinkedList都有序,有索引,可重复。
-
请简述ArrayList和Vector的区别
- ArrayList和Vector底层都是Object数组,查找快,增删慢
- ArrayList和Vector都继承了List接口
- ArrayList调用默认无参构造是,创建一个长度为0的空数组,当添加第一个元素时数组长度扩展为10,Vector调用默认无参构造时创建一个长度为10的空数组
- ArrayList扩容后数组为原长度的1.5倍,Vector扩容后数组长度为原长度的2倍
- ArrayList是非线程安全,Vector是线程安全的,但是效率低于ArrayList
-
请简述ArrayList和LinkedList的区别
- 都继承了List接口
- 都是非线程安全
- ArrayList底层实现是数组,LinkedList底层实现是双向链表
- ArrayList查找快,增删慢,LinkedList 增删快,查找慢
本文作者:风于野
本文链接:https://www.cnblogs.com/CodeStones/p/15429013.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步