• 常用的Java集合框架你知道多少?


    目录

    一、UML类图

    二、List

    特点:

    遍历:

    扩容:

    ​编辑

    如何实现?

    1.ArrayList

    2.LinkedList

    3.Vector

    4.CopyOnWriteArrayList

    ArrayList remove 的注意点

    三、Set

    特点:

    遍历:

    扩容:

    实现:

    01.HashSet

    02.TreeSet

    03.排序:

    四、Map

    特点:

    扩容:

    遍历:

    实现:

    01.HashMap

    02.HashTable

    03.ConcurrentHashMap

    04.TreeMap

    05.LinkedHashMap


    一、UML类图

    UML关系图:

    注:这是老版,新版还添加了其他的类

    UML:统一建模语言

    想更好的了解UML可以去这个网址:

    UML类图几种关系的总结http://www.uml.org.cn/oobject/201609062.asp


    二、List

    特点:

    元素有序,且可重复

    遍历:

    下标,foreach,迭代器

    扩容:

    • 初始容量10,负载因子0.5,扩容增量0.5倍
    • 新容量 = 原容量 + 原容量 * 0.5  , 如 ArrayList的容量为10,一次扩容后是容量为15

    利用反射机制

    1. @Test
    2. public void listKuo() throws Exception {
    3. List<Integer> list=new ArrayList<>();
    4. for (int i = 0; i <= 100; i++) {
    5. list.add(i);
    6. System.out.println("i:"+i);
    7. System.out.println("len:"+getListEleSize(list));
    8. }
    9. }
    10. private int getListEleSize(List obj) throws Exception{
    11. Class<? extends List> clazz=obj.getClass();
    12. java.lang.reflect.Field f=clazz.getDeclaredField("elementData");
    13. f.setAccessible(true);
    14. Object[] object= (Object[])f.get(obj);
    15. return object.length;
    16. }

    如何实现?

    1.ArrayList

    • 简单数据结构,超出容量自动扩容,动态数组
    • 内部实现是基于基础的对象数组的
    • 随机访问快(最快)
    • 不适合随机增加或删除
    • 线程不安全

    2.LinkedList

    • LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部
    • 线程不安全
    • LinkedList可被用作堆栈(stack)【包括了push,pop方法】,队列(queue)或双向队列(deque)
    • 以双向链表实现,链表无容量限制,允许元素为null,线程不安全
    • 适合做随机的增加或删除

    3.Vector

    • 线程安全
    • 并行性能慢,不建议使用

    4.CopyOnWriteArrayList

    • 写时复制
    • 线程安全
    • 适合于读多,写少的场景
    • 写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array
    • 比Vector性能高
    • 最终一致性
    • 实现了List接口,使用方式与ArrayList类似

    ArrayList remove 的注意点

    设置下面这个方法,更方便检查

    项目右键找到

    点击Add Library中的JUnit,然后点击下一步

     

    出现以下界面选择JUnit4,再应用就可以了

    用Debug As中的JUnit Test运行

    如果正确那么那个长框中就为绿色,错误为红色(如下图)

    数据准备:为方便演示,需要有紧挨在一起的两个或多个相同的元素

    1. private List<Integer> list;//成员变量
    2. //每次运行都会执行Before方法
    3. @Before
    4. public void setup() {
    5. list = new ArrayList<>();
    6. list.add(1);
    7. list.add(2);
    8. list.add(3);
    9. list.add(3);
    10. list.add(4);
    11. }

    各种输出方法

    1. /**
    2. * 删除集合中所有为3的元素
    3. */
    4. @Test
    5. public void remove01() {
    6. for (int i = 0; i < list.size(); i++) {
    7. if (list.get(i) == 3)
    8. list.remove(i);// 错误,因为数组下标会发生改变(移位)
    9. }
    10. System.out.println(list);// [1, 2, 3, 4]
    11. }
    12. @Test
    13. public void remove02() {
    14. for (int i = 0; i < list.size(); i++) {
    15. if (list.get(i) == 3)
    16. list.remove(i--);// 正确,删除之后下标往上移了一位,所以又识别到了3
    17. }
    18. System.out.println(list);// [1, 2, 4]
    19. }
    20. @Test
    21. public void remove03() {
    22. for (int i = list.size() - 1; i >= 0; i--) {
    23. if (list.get(i) == 3) {
    24. list.remove(i);// 正确,这是从后往前进行检测
    25. }
    26. }
    27. System.out.println(list);// [1, 2, 4]
    28. }
    29. @Test
    30. public void remove04() {
    31. for (Integer i : list) {
    32. if (i == 3)
    33. list.remove(i);// 错误,维护的值不相等了
    34. }
    35. System.out.println(list);
    36. }
    37. @Test
    38. public void remove05() {
    39. // 迭代器
    40. Iterator<Integer> it = list.iterator();
    41. while (it.hasNext()) {
    42. if (it.next() == 3) {
    43. it.remove();// 正确
    44. }
    45. }
    46. System.out.println(list);
    47. }
    48. @Test
    49. public void remove06() {
    50. Iterator<Integer> it = list.iterator();
    51. while (it.hasNext()) {
    52. Integer value = it.next();
    53. if (value == 3) {
    54. list.remove(value);
    55. }
    56. }
    57. System.out.println(list);//错误
    58. }
    59. @Test
    60. public void remove07() {
    61. list.remove(2);//删除下标为2的数
    62. System.out.println(list);//[1, 2, 3, 4]
    63. }

    三、Set

    特点:

    无序,不重复

    遍历:

    foreach,迭代器

    扩容:

    初始容量16,负载因子0.75,扩容增量1倍

    实现:

    01.HashSet

    • 它存储唯一元素并允许空值(依据对象的hashcode来确定该元素是否存在)
    • 由HashMap支持
    • 不保持插入顺序
    • 非线程安全
    • 性能参数:初始容量,负载因子(默认值: 初始容量16,负载因子0.75    示例:new HashSet<>(20, 0.5f);)

    示例

    1. package com.pf.dao;
    2. import java.util.ArrayList;
    3. import java.util.HashSet;
    4. import java.util.Iterator;
    5. import java.util.List;
    6. import java.util.Set;
    7. import org.junit.Before;
    8. import org.junit.Test;
    9. public class SetDemo {
    10. private List<Integer> list = new ArrayList<>();
    11. private Set<Integer> set = new HashSet<>();
    12. @Before
    13. public void setup() {
    14. list.add(1);
    15. list.add(1);
    16. list.add(2);
    17. list.add(2);
    18. list.add(3);
    19. list.add(4);
    20. list.add(5);
    21. set.add(1);
    22. set.add(1);
    23. set.add(2);
    24. set.add(4);
    25. set.add(5);
    26. set.add(3);
    27. }
    28. /**
    29. * 去重
    30. */
    31. @Test
    32. public void test01() {
    33. List<Integer> tmp = new ArrayList<>(new HashSet<Integer>(list));
    34. System.out.println(tmp);
    35. }
    36. @Test
    37. public void test02() {
    38. for(Integer e:set) {
    39. System.out.println(e);
    40. }
    41. }
    42. public void test03() {
    43. Iterator<Integer> it = set.iterator();
    44. while(it.hasNext()) {
    45. System.out.println(it.next());
    46. }
    47. }
    48. }

    02.TreeSet

    • 是一个包含有序的且没有重复元素的集合
    • 作用是提供有序的Set集合,自然排序或者根据提供的Comparator进行排序
    • TreeSet是基于TreeMap实现的

    03.排序:

    java.lang.Comparable

    java.util.Comparator

    第一种:根据sid进行的升序(如果想降序的话,只需要改成o2.getSid()-o1.getSid())

    1. package com.pf.dao;
    2. public class Student {
    3. private Integer sid;
    4. private String sname;
    5. private int age;
    6. public Integer getSid() {
    7. return sid;
    8. }
    9. public void setSid(Integer sid) {
    10. this.sid = sid;
    11. }
    12. public String getSname() {
    13. return sname;
    14. }
    15. public void setSname(String sname) {
    16. this.sname = sname;
    17. }
    18. public int getAge() {
    19. return age;
    20. }
    21. public void setAge(int age) {
    22. this.age = age;
    23. }
    24. @Override
    25. public int hashCode() {
    26. final int prime = 31;
    27. int result = 1;
    28. result = prime * result + age;
    29. result = prime * result + ((sid == null) ? 0 : sid.hashCode());
    30. result = prime * result + ((sname == null) ? 0 : sname.hashCode());
    31. return result;
    32. }
    33. @Override
    34. public boolean equals(Object obj) {
    35. if (this == obj)
    36. return true;
    37. if (obj == null)
    38. return false;
    39. if (getClass() != obj.getClass())
    40. return false;
    41. Student other = (Student) obj;
    42. if (age != other.age)
    43. return false;
    44. if (sid == null) {
    45. if (other.sid != null)
    46. return false;
    47. } else if (!sid.equals(other.sid))
    48. return false;
    49. if (sname == null) {
    50. if (other.sname != null)
    51. return false;
    52. } else if (!sname.equals(other.sname))
    53. return false;
    54. return true;
    55. }
    56. @Override
    57. public String toString() {
    58. return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
    59. }
    60. public Student() {
    61. super();
    62. // TODO Auto-generated constructor stub
    63. }
    64. public Student(Integer sid, String sname, int age) {
    65. super();
    66. this.sid = sid;
    67. this.sname = sname;
    68. this.age = age;
    69. }
    70. }
    1. private List<Integer> list = new ArrayList<>();
    2. private Set<Integer> set = new HashSet<>();
    3. @Before
    4. public void setup() {
    5. list.add(1);
    6. list.add(1);
    7. list.add(2);
    8. list.add(2);
    9. list.add(3);
    10. list.add(4);
    11. list.add(5);
    12. set.add(1);
    13. set.add(1);
    14. set.add(2);
    15. set.add(4);
    16. set.add(5);
    17. set.add(3);
    18. }
    19. @Test
    20. public void test04() {
    21. TreeSet<Student> stu = new TreeSet<>(new Comparator<Student>() {
    22. @Override
    23. public int compare(Student o1, Student o2) {//排序
    24. return o1.getSid()-o2.getSid();
    25. }
    26. });
    27. stu.add(new Student(1,"zs", 18));
    28. stu.add(new Student(1,"zs", 18));
    29. stu.add(new Student(2,"ls", 19));
    30. stu.add(new Student(4,"lihao", 10));
    31. stu.add(new Student(7,"lihao", 18));
    32. stu.add(new Student(5,"zengfanyan", 20));
    33. stu.add(new Student(3,"we", 30));
    34. //删除
    35. //stu.remove(new Student(4, "lihao", 10));
    36. for(Student s: stu) {
    37. System.out.println(s);
    38. }
    39. }

    效果图:

     第二种:

    在实体类(student)中继承一个接口

    public class Student implements Comparable<Student>{

    然后实现一个方法

    1. @Override
    2. public int compareTo(Student o) {
    3. return this.getSid() - o.getSid();
    4. }

    最后再测试类中把排序删掉

    1. @Test
    2. public void test04() {
    3. TreeSet<Student> stu = new TreeSet<>();
    4. stu.add(new Student(1,"zs", 18));
    5. stu.add(new Student(1,"zs", 18));
    6. stu.add(new Student(2,"ls", 19));
    7. stu.add(new Student(4,"lihao", 10));
    8. stu.add(new Student(7,"lihao", 18));
    9. stu.add(new Student(5,"zengfanyan", 20));
    10. stu.add(new Student(3,"we", 30));
    11. //删除
    12. //stu.remove(new Student(4, "lihao", 10));
    13. for(Student s: stu) {
    14. System.out.println(s);
    15. }
    16. }

    四、Map

    特点:

    无序,键值对,键不能重复,值可以重复,键重复则覆盖,没有继承Collection接口

    扩容:

    初始容量16,负载因子0.75,扩容增量1倍

    遍历:

    先获取所有键的Set集合,再遍历(通过键获取值)

    取出保存所有Entry的Set,再遍历此Set即可

    1. package com.pf.dao;
    2. import java.util.HashMap;
    3. import java.util.Iterator;
    4. import java.util.Map;
    5. import java.util.Map.Entry;
    6. import org.junit.Before;
    7. import org.junit.Test;
    8. public class MapDemo {
    9. private Map<String, Object> map=new HashMap<String, Object>();
    10. @Before
    11. public void setup() {
    12. map.put("1", "zhuzhu");
    13. map.put("1", "aa");
    14. map.put("2", "she");
    15. map.put("3", "he");
    16. //如果键值对没有就添加进去
    17. map.putIfAbsent("1", "zzz");
    18. }
    19. @Test
    20. public void test01() {
    21. Iterator<String> it = map.keySet().iterator();//通过获取键的集合来获取迭代器
    22. while(it.hasNext()) {
    23. String key=it.next();
    24. System.out.println(map.get(key));
    25. }
    26. }
    27. @Test
    28. public void test02() {
    29. Iterator<Entry<String, Object>> it = map.entrySet().iterator();
    30. //比上面的方法略微快一点点,如果对所有的map集合一次遍历完成之后都要去处理的话,就用这种更好
    31. while(it.hasNext()) {
    32. Entry<String, Object> e = it.next();
    33. System.out.println("key = " + e.getKey()+"value = "+e.getValue());
    34. }
    35. }
    36. }

    实现:

    01.HashMap

    • 线程不安全,最常用,速度快
    • 内部采用数组来存放数据

    基本原理:

    put执行过程

     Table数组中的的Node

    1》链表结构示意图

    数据结构:链表 - 简书本文内容:1、 什么是链表?2、 链表共分几类?3、 链表的 C 实现! 总表:《数据结构?》 工程代码 Github: Data_Structures_C_Implemen...https://www.jianshu.com/p/73d56c3d228c

    2》红黑树结构示意图

    红黑树是什么?红黑树特点有哪些?-奇Q工具网对于红黑树你了解多少呢?很多刚刚接触java的人都不知道红黑树是什么,那么下面就一起来看一下红黑树的概念以及它的特点吧!一、什么是红黑树?红黑树,是一种自平衡二叉查找树,是在计算机科学当中,所用到的一种数据结构,最典型的用途就是实现关联数组。红黑树是一种特化的AVL树,也就是平衡二叉树,都是在进行插入和删除操作的的时候,通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。红黑树是复杂的,可是,它的最坏情况运行时间也是非常良好的,并且在实践中是高效的。红黑树可以在O(log n)时间内做查找icon-default.png?t=M5H6https://qqe2.com/java/post/1321.html 可以在下面网站中测试(可以在这个网站学习数据类型)Data Structure Visualization http://www.rmboot.com/注:流程图中绿色标出的部分为JDK8新增的处理逻辑,目的是在Table[i]中的Node节点数量大于8时,通过红黑树提升查找速度。 

    02.HashTable

    线程安全,不太常用

    1. @Test
    2. public void test03() {
    3. Map<Integer, Object> table = new Hashtable<Integer, Object>();
    4. table.put(1, "zfm");
    5. table.put(2, "zfm2");
    6. table.put(3, "zfm3");
    7. table.put(4, "zfm4");
    8. Iterator<Integer> it = table.keySet().iterator();
    9. while(it.hasNext()) {
    10. int key=it.next();
    11. System.out.println(table.get(key));
    12. }
    13. }

    03.ConcurrentHashMap

    线程安全,比HashTable性能高(一桶一锁,加强比较并替换操作)

    1. @Test
    2. public void test04() {
    3. Map<Integer, Object> cmap = new ConcurrentHashMap<Integer, Object>();
    4. cmap.put(1, "zfm");
    5. cmap.put(2, "zfm2");
    6. cmap.put(3, "zfm3");
    7. cmap.put(4, "zfm4");
    8. Iterator<Integer> it = cmap.keySet().iterator();
    9. while(it.hasNext()) {
    10. int key=it.next();
    11. System.out.println(cmap.get(key));
    12. }
    13. }

    04.TreeMap

    • key值按一定的顺序排序
    • 添加或获取元素时性能较HashMap慢(因为需求维护内部的红黑树,用于保证key值的顺序)

    这是降序排列

    1. @Test
    2. public void test05() {
    3. TreeMap<Integer, Object> treeMap = new TreeMap<Integer, Object>(new Comparator<Integer>() {
    4. @Override
    5. public int compare(Integer o1, Integer o2) {
    6. return o2 - o1;
    7. }
    8. });
    9. treeMap.put(1, "zs1");
    10. treeMap.put(3, "zs3");
    11. treeMap.put(2, "zs2");
    12. treeMap.put(4, "zs4");
    13. Iterator<Integer> it = treeMap.keySet().iterator();
    14. while(it.hasNext()) {
    15. int key = it.next();
    16. System.out.println(treeMap.get(key));
    17. }
    18. }

    注:如果在new的时候不记得了可以按住Ctrl键再将鼠标移到TreeMap上点击就可以跳转源代码进行查看了

    05.LinkedHashMap

    • 继承HashMap
    • LinkedHashMap是有序的,且默认为插入顺序(当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了)
    1. @Test
    2. public void test06() {
    3. Map<String, String> linkedHashMap = new LinkedHashMap<>();
    4. linkedHashMap.put("name1", "josan1");
    5. linkedHashMap.put("name2", "josan2");
    6. linkedHashMap.put("name3", "josan3");
    7. Set<Entry<String, String>> set = linkedHashMap.entrySet();
    8. Iterator<Entry<String, String>> iterator = set.iterator();
    9. while(iterator.hasNext()) {
    10. Entry entry = iterator.next();
    11. String key = (String) entry.getKey();
    12. String value = (String) entry.getValue();
    13. System.out.println("key:" + key + ",value:" + value);
    14. }
    15. }

    工具类

    • Collections:提供一组静态方法操作集合
    • Arrays:提供一组静态方法操作数组

  • 相关阅读:
    撰写英文文献有哪些技巧?
    Asp .Net Core 系列:集成 Ocelot+Nacos+Swagger+Cors实现网关、服务注册、服务发现
    状态压缩dp蒙德里安的梦想
    父组件与子组件的属性透传
    关于#matlab#的问题:我看到了gp-ols算法,请问gp我可以理解为是线性拟合吗,还是利用树结构寻优
    对自己LRU算法代码的优化
    Python3 OS 文件/目录方法
    【echart】饼图 legend tooltip格式化比例为0不显示
    MAC安装redis的简单方法
    HTML5期末大作业:简单的学生网页作业源码 基于html企业官网项目的设计与实现【艺术官网】
  • 原文地址:https://blog.csdn.net/m0_67331668/article/details/125483431