导读:
在实际的业务开发中,我们几乎离不开集合的使用。无论是使用集合进行数据存储还是使用集合工具类进行排序等相关操作,都需要对它们进行一定的了解,对每一种集合的适用场景,优缺点,常用方法,特点等等进行足够的理解,对集合工具类的使用进行掌握。如此,在实际的开发过程中我们才能够根据按需分配,按需执行。
附上思维导图:
使用场景:
1.存放数据是否为列表形式,且存放数据有序:->List
默认: ->ArrayList
查询效率较高,增删改效率较低: ->ArrayList,Vector
线程安全: ->Vector
查询效率较低,增删改效率较高: ->LinkedList
2.存放数据是否不可重复: ->Set
默认: ->HashSet
可以排序,必须重写equals()与hashcode()方法: ->TreeSet
存放数据有序: ->LinkedHashSet
3.存放数据是否按K/V的形式: ->Map
默认: ->HashMap
是否允许存在空键或者空值的情况: ->HashMap
线程安全: ->Hashtable,ConcurrentHashMap
效率高: ->ConcurrentHashMap
存放数据有序: ->LinkedHashMap,ConcurrentHashMap
ArrayList:通过数组实现,通过数组复制实现数组的扩容
附上代码简单了解:
1 public class OverrideArrayList { 2 //定义一个Object类对象数组 3 public Object[] elementsData; 4 //集合的大小 5 public int size; 6 7 //初始化数组大小10 8 public OverrideArrayList(){ 9 this(10); 10 } 11 12 //初始化数组 13 public OverrideArrayList(int InitCapacity){ 14 if(InitCapacity<0) { 15 try { 16 System.out.println("初始化数值异常!"); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 } 21 elementsData=new Object[InitCapacity]; 22 } 23 24 //判断集合是否为空 25 public boolean isEmpty() { 26 return size==0; 27 } 28 29 public void add(Object obj) { 30 //数组扩容,判断size是否大于数组的长度 31 if(size==elementsData.length) { 32 Object[] newArray=new Object[size*2+1]; 33 //原数组0的位置复制到新数组0的位置,数组元素为原数组数据 34 System.arraycopy(elementsData, 0, newArray, 0, elementsData.length); 35 //转化为新的数组 36 elementsData=newArray; 37 } 38 elementsData[size++]=obj; 39 } 40 41 //根据索引位置查找数组对应下标的值 42 public Object get(int index) { 43 rangeCheck(index); 44 return elementsData[index]; 45 } 46 47 //在对应索引位置更改对应的值 48 public void set(int index,Object obj) { 49 elementsData[index]=obj; 50 } 51 52 53 //判断索引位置与数组大小,越界则抛出异常 54 public void rangeCheck(int index) { 55 if(index<0 || index>=size) { 56 try { 57 throw new Exception(); 58 } catch (Exception e) { 59 e.printStackTrace(); 60 } 61 } 62 } 63 64 //测试 65 public static void main(String[] args) { 66 OverrideArrayList list=new OverrideArrayList(); 67 list.add(1); 68 list.add(new Date()); 69 System.out.println(list.isEmpty()); 70 System.out.println(list.size); 71 list.set(0, 2); 72 System.out.println(list.size); 73 list.add("测试"); 74 System.out.println(list.get(2)); 75 } 76 }
效果截图:
LinkedList:底层通过链表实现
1 //模拟链表实体类 2 public class Node { 3 //上一个节点 4 public Node previous; 5 //下一个节点 6 public Node next; 7 //自身节点对象 8 public Object obj; 9 10 public Node() { 11 12 } 13 14 public Node(Node previous, Node next, Object obj) { 15 super(); 16 this.previous = previous; 17 this.next = next; 18 this.obj = obj; 19 } 20 21 public Node getPrevious() { 22 return previous; 23 } 24 public void setPrevious(Node previous) { 25 this.previous = previous; 26 } 27 public Node getNext() { 28 return next; 29 } 30 public void setNext(Node next) { 31 this.next = next; 32 } 33 public Object getObj() { 34 return obj; 35 } 36 public void setObj(Object obj) { 37 this.obj = obj; 38 } 39 40 }
1 //链表操作方法实现 2 public class TestLinkedList { 3 //获取节点的头和尾以及链的长度大小 4 private Node first; 5 private Node last; 6 private int size; 7 8 //新增元素的方法 9 public void add(Object obj) { 10 Node n=new Node(); 11 //链表的头节点 12 if(first==null) { 13 n.setPrevious(null); 14 n.setObj(obj); 15 n.setNext(null); 16 first=n; 17 last=n; 18 }else { 19 //直接往last节点后增加新的节点 20 n.setPrevious(last); 21 n.setObj(obj); 22 n.setNext(null); 23 //下一个节点 24 last.setNext(n); 25 last=n; 26 } 27 size++; 28 } 29 30 //获取size 31 public int size() { 32 return size; 33 } 34 35 //根据下标获取元素的值 36 public Object get(int index) { 37 //获取index位置上的node对象 38 Node temp=node(index); 39 checkRange(index); 40 if(temp!=null) { 41 //返回当前节点的对象的值 42 return temp.obj; 43 } 44 return null; 45 } 46 47 //索引位置对应node对象获取->first:头 ->next:下一个节点 48 public Node node(int index) { 49 Node temp=null; 50 if(first!=null) { 51 temp=first; 52 //如果下一个节点不为空 53 for(int i=0;i) { 54 temp=temp.next; 55 } 56 } 57 return temp; 58 59 } 60 61 //设置index对应的对象的值 62 public Object set(int index) { 63 return null; 64 } 65 66 //删除index对应的对象的值 67 public void remove(int index) { 68 Node temp=node(index); 69 if(temp!=null) { 70 Node up=temp.previous; 71 Node down=temp.next; 72 //上一个节点的头指向下一个节点的尾 73 up.next=down; 74 } 75 size--; 76 77 } 78 79 //检查是否越界 80 public void checkRange(int index) { 81 if(index<0 || index>=size) { 82 try { 83 throw new Exception(); 84 } catch (Exception e) { 85 // TODO Auto-generated catch block 86 e.printStackTrace(); 87 } 88 } 89 } 90 91 //测试 92 public static void main(String[] args) { 93 TestLinkedList list=new TestLinkedList(); 94 //数据添加 95 list.add("hello"); 96 list.add("abc"); 97 list.add(new Date()); 98 //数据移除 99 list.remove(2); 100 System.out.println("集合大小:"+list.size()); 101 System.out.println("当前索引1对应的值为:"+list.get(1)); 102 103 } 104 }
简单了解:
1 public class LinkedListTest { 2 private List list = new LinkedList(); 3 4 @Test 5 public void test() { 6 //添值 7 list.add(0,1); 8 list.add(1,"2"); 9 list.add(2,'3'); 10 //设值 11 list.set(0, 123); 12 //集合大小 13 System.out.println(list.size()); 14 //取值 15 System.out.println(list.get(0)); 16 //获取对应值的索引下标 若值不存在返回-1 17 System.out.println(list.indexOf(123)); 18 //获取对应下标的list迭代器 19 ListIterator listIterator=list.listIterator(1); 20 //迭代器是否存在下一个值 21 System.out.println(listIterator.next()); 22 //获取list集合的list迭代器 23 ListIterator listIterator1=list.listIterator(); 24 //集合切割,生成从索引为1到3 -> [1,3)的新集合 25 List newList=list.subList(1,3); 26 //集合转变为数组 27 Object [] obj=newList.toArray(); 28 //遍历数组 29 for(Object ob:obj){ 30 System.out.println(ob); 31 } 32 } 33 34 }
效果截图:
ConcurrentHashMap:底层是数组加链表或者红黑树实现,内部使用到分段锁技术保证多线程的环境安全
简单了解:
1 public class ConcurrentHashMapTest { 2 //ConcurrentHashMap:本身就是一个线程安全的,有序 3 private ConcurrentHashMap
详细了解:https://www.cnblogs.com/banjinbaijiu/p/9147434.html
文章若有什么不当之处,欢迎指正。