Java进阶九—数组问题(集合框架)

发布时间:2023年12月24日

Java进阶九—数组问题(集合框架)

一.原生数组带来的问题

  • 原生数组容易造成超出边界,如果非要使用传统的数组,增删改查,就要用到数据结构,非常复杂
  • CRUD是指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写
    package com.array;
    
    import org.junit.Test;
    
    public class ArrayTest {
    
        public static final int SIZE = 3;
    
        @Test
        public void testArray() {
    
            int[] array = new int[SIZE];
    
            array[0] = 1;
            array[1] = 2;
            array[2] = 3;
            array[3] = 4;
    
            for (int arrays :array) {
                System.out.println(arrays);
            }
        }
    }
    

由此我们抛出Java Conllections FrameWork即Java集合框架,也可称为函数库?

二.Conllections家族?

  • Java集合框架是一个包含一系列实作可重复使用集合的数据结构的类别和界面集合
  • Java集合大致可以分为两大体系,一个是Collection,另一个是Map

?

三.?黑帮的帮规?

集合 (Java Platform SE 8) (oracle.com)

  • lterables集合层次结构中的根接口,可以理解为保护伞
  • 一般黑老大不会自己出手,会让手下三个组织来办事,所以用的时候找类来实现
  • 黑老大定下的规矩(方法),手下三个组织必须遵守。其实就是Collection的方法,实现的三个接口List,Queue,Set必须重写方法。

?四.ArrayList

?ArrayList (Java Platform SE 8 ) (oracle.com)

ArrayList?类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。

ArrayList?继承了?AbstractList?,并实现了?List?接口可以自动扩容

?1.添加

这个E代表泛型,表示任意变量类型。?

public void arrayListTest() {

        // 任意类型
        ArrayList arrayList = new ArrayList();

        arrayList.add(1);
        arrayList.add(4.3);
        arrayList.add("C");
        arrayList.add("fuck");

        System.out.println(arrayList);

        // 规定为String类型,泛型限定
        ArrayList<String> arrayList1 = new ArrayList<>();

        arrayList1.add("fu");
        arrayList1.add("ck");

        System.out.println(arrayList1);


    }

?

泛型也可以是对象,创建一个Student类?

package com.array;

public class Student {
    
    private String name;

    private int age;

    public Student() {
        
    }

    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
 public void arrayListTest() {

        // 泛型为Student
        ArrayList<Student> arrayList = new ArrayList<>();

        arrayList.add(new Student("fuck",22));
        arrayList.add(new Student("LiLi",33));

        System.out.println(arrayList);


    }

?

还有一种添加可以指定下标位置。?

  public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(3);

        // 添加下标时,要注意添加的位置,添加的位置已有的位置前或中间,不能是后面。
        arrayList.add(0,0);
        arrayList.add(2,2);

        System.out.println(arrayList);

    }

2.合并?

  public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(3);

        // 添加下标时,要注意添加的位置,添加的位置已有的位置前或中间,不能是后面。
        arrayList.add(0,0);
        arrayList.add(2,2);

        ArrayList<Integer> arrayList1 = new ArrayList<>();

        arrayList1.add(4);

        // 将arrayList1合并到arrayList
        arrayList.addAll(arrayList1);

        System.out.println(arrayList);

    }

?它是如何实现的,看源码

集合转换成普通数组,拷贝数组并返回。?

第二种是选择下标插入,非常简单与添加使用的方式一样,我应该不用说了。

3.将集合转换成数组

public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);

        // 需要Object类型的数组去接收
        Object[] array = arrayList.toArray();
        
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }

    }

4.清空与拷贝?

 public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);

        System.out.println(arrayList);

        // 清空
        arrayList.clear();
        System.out.println(arrayList);
    }

 public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);

        System.out.println(arrayList);

        ArrayList<Integer> arrayList1 = (ArrayList<Integer>) arrayList.clone();

        // 拷贝
        System.out.println(arrayList1);

    }

5. 查看集合中是否有这个元素

 public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);

       // 返回boolean类型
        boolean number1 = arrayList.contains(3);
        System.out.println(number1);
        boolean number2 = arrayList.contains(5);
        System.out.println(number2);

    }

?

6. 获取集合的容量与需要的下标值,与任何遍历

集合之所以可以直接输出不用遍历,是因为它重新了toString方法。

public void arrayListTest() {

        // 泛型为整数与浮点数时要使用他们的包装类
        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);

        // 集合容量
        System.out.println(arrayList.size());

        // 下标为2的值
        int indexTwo = arrayList.get(2);
        System.out.println(indexTwo);


        // 遍历,并给每一个元素加2,
        // 遍历的作用:不仅要输出,还有操作

        // 方法一:for循环数组遍历时使用length,而集合遍历使用size
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+2+"\t");
        }

        System.out.println();
        
        // 方法二:增强for循环
        for (Integer value : arrayList) {
            System.out.print(value+2+"\t");
        }

7. 给值找下标

  public void arrayListTest() {
        
        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("Man");
        arrayList.add("Tom");
        arrayList.add("Fuck");
        arrayList.add("LiLi");
        arrayList.add("Fuck");
        arrayList.add("JiJi");

        // 从前往后,查找最近的
        System.out.println(arrayList.indexOf("Fuck"));
        // 从后往前,查找最近的
        System.out.println(arrayList.lastIndexOf("Fuck"));
    }

8. 查看集合是否为空

public void arrayListTest() {

        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("Man");
        arrayList.add("Tom");
        arrayList.add("Fuck");

        // 集合是否为空
        System.out.println(arrayList.isEmpty());


        ArrayList<String> arrayList1 = new ArrayList<>();

        // 集合是否为空
        System.out.println(arrayList1.isEmpty());
    }

9. 删除

 public void arrayListTest() {

        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("Man");
        arrayList.add("Tom");
        arrayList.add("Fuck");
        arrayList.add(null);

        System.out.println(arrayList);

        // 指定值删除,删除值为空的
        System.out.println(arrayList.remove(null));

        System.out.println(arrayList);
    }

public void arrayListTest() {

        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("Man");
        arrayList.add("Tom");
        arrayList.add("Fuck");
        arrayList.add(null);

        System.out.println(arrayList);

        // 指定下标删除,删除值为空的
        System.out.println(arrayList.remove(3));

        System.out.println(arrayList);
    }

?

 public void arrayListTest() {

        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("Man");
        arrayList.add("Tom");
        arrayList.add("Fuck");
        arrayList.add(null);

        System.out.println(arrayList);

        ArrayList<String> arrayList1 = new ArrayList<>();

        arrayList1.add("Fuck");
        arrayList1.add(null);

        // 根据arrayList1集合元素删除arrayList里的相同元素
        arrayList.removeAll(arrayList1);

        System.out.println(arrayList);

    }

?10.两个集合取交集(相同元素)

 public void arrayListTest() {

        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);

        System.out.println(arrayList);

        ArrayList<Integer> arrayList1 = new ArrayList<>();

        arrayList1.add(3);
        arrayList1.add(5);

        System.out.println(arrayList1);

        // 取交集
        System.out.println(arrayList.retainAll(arrayList1));

        // 原理是取完交集后,放在arrayList中
        System.out.println(arrayList);

    }

11. 替换

 public void arrayListTest() {

        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);

        System.out.println(arrayList);

        // 把3替换成4
        arrayList.set(2,4);

        System.out.println(arrayList);

    }

12.排序与倒序?

?由于此方法要使用拉姆达表达式,使用我们采用另一种方法。?

集合 (Java Platform SE 8 ) (oracle.com)

public void arrayListTest() {

        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(0);
        arrayList.add(44);

        System.out.println(arrayList);

        // 排序,从小到大
        Collections.sort(arrayList);

        System.out.println(arrayList);

        // 倒序
        Collections.reverse(arrayList);

        System.out.println(arrayList);
        
    }

?13.取指定下标范围的值

public void arrayListTest() {

        ArrayList<Integer> arrayList = new ArrayList<>();

        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(0);
        arrayList.add(44);

        System.out.println(arrayList);

        // 查找下标1到3的值;
        System.out.println(arrayList.subList(1,4));

        // 之所以下标是1-4是因为,这个查找原理是这样的:1 <= 下标范围 < 4

    }

五.Linked链表

  • ArrayList数组集合,增删慢,查询快
  • LinkedList链表集合,增删快,查询慢

?数组集合之所以增删慢,是因为增删时集合内元素要移动

?链表集合增删快,是因为链表集合增删时内部元素不需要移动

六.LinkedList一带而过?

  • 链表是数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址
  • 链表可分为单向链表和双向链表
  • 由于黑老大定下的规矩,所以它跟ArrayList方法差不多相同。

LinkedList (Java Platform SE 8 ) (oracle.com)

?七.iterator 迭代器初试

  • 迭代是重复反馈过程的活动,其目的通常是为了接近并到达所需目标或结果
  • 每一次对过程的重复被称为一次“迭代”,而每一次迭代的结果会被用来作为下一次迭代的初始值

?迭代器Iterator用于Conllections家族?,不管用于ArrayList还是LinkedList都可以迭代输出

 public void arrayListTest() {

        // 数组集合
        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("Tom");
        arrayList.add("Fuck");
        arrayList.add("Lise");

        // 使用方式
        Iterator<String> iterator = arrayList.iterator();
        // hasNext()判断是否有值
        while (iterator.hasNext()) {
            String value = iterator.next();
            System.out.println(value);
        }
    }

public void arrayListTest() {

        // 链表集合
        LinkedList<String> linkedList = new LinkedList<>();

        linkedList.add("Tom");
        linkedList.add("Fuck");
        linkedList.add("Lise");

        // 使用方式
        Iterator<String> iterator = linkedList.iterator();
        // hasNext()判断是否有值
        while (iterator.hasNext()) {
            String value = iterator.next();
            System.out.println(value);
        }
    }

八.fori、增强for、迭代器的区别、谈谈三者性能

  • for循环适合数据的读取与修改
  • 增强for循环适合数据的读取
  • Iterator不要使用for循环嵌套使用,适合数据的读取与修改
      public void arrayListTest() {
    
            // 链表集合
            LinkedList<String> linkedList = new LinkedList<>();
    
            linkedList.add("Tom");
            linkedList.add("Fuck");
            linkedList.add("Lise");
    
            // 使用方式
            Iterator<String> iterator = linkedList.iterator();
            // hasNext()判断是否有值
            while (iterator.hasNext()) {
                String value = iterator.next();
                // 删除Tom
                if (value.equals("Tom")) {
                    // 要使用iterator自带的remove()方法
                    iterator.remove();
                }
            }
            System.out.println(linkedList);
        }

增强for循环是一个小型的迭代器了,如果一定要在增强for循环中修改集合的话可以使用迭代器,但不建议在增强for循环中直接修改

?谈谈三者性能:比较时间复杂度

如果是 ArrayList ,用三种方式遍历的速度是for循环>Iterator>增强for循环,速度级别基本一致,一般都会用for循环或者增强for循环,因为Iterator写法相对复杂一些


如果是 LinkedList,则三种方式遍历的差距很大了,数据量大时越明显,Iterator>增强for循环>>>for循环,推荐使用增强for循环或者Iterator

List遍历:for,foreach Iterator 速度比较_list迭代器遍历执行慢-CSDN博客

九.Set和HashSet?

?HashSet?基于?HashMap?来实现的,是一个不允许有重复元素的集合,允许有 null 值,是无序的,即不会记录插入的顺序。

 public void setTest() {

        // 使用Hash函数实现HashSet,元素无序,且不重复
        HashSet<String> hashSet = new HashSet<>();

        hashSet.add("Tom");
        hashSet.add("Fuck");
        hashSet.add("LiLi");
        hashSet.add("LiLi");
        hashSet.add("Fuck");

        System.out.println(hashSet);
        
        // 之所以输出后没有顺序且是唯一,是由于hashSet的每一个元素都会给应该hash值
        // hash值相当与身份证,不重复是唯一的
    }

关于Java的Hash算法的深入理解-CSDN博客

十.LinkedHashSet?

如果要创建有序集合呢?LinkedHashSet便是有序的不重复的

 public void setTest() {

        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();

        linkedHashSet.add("Tom");
        linkedHashSet.add("Fuck");
        linkedHashSet.add("LiLi");
        linkedHashSet.add("LiLi");
        linkedHashSet.add("Fuck");

        System.out.println(linkedHashSet);

    }

十一.Map、HashMap、Entry?

?HashMap (Java Platform SE 8 ) (oracle.com)

 public void mapTest() {

        // 有两个泛型:第一个为key(钥匙),第二个为value(值)
        HashMap<Integer,String> hashMap = new HashMap<>();

        hashMap.put(10000000,"Fuck");
        hashMap.put(10000001,"Tom");
        hashMap.put(10000002,"LiLi");
        hashMap.put(10000003,"Man");

        System.out.println(hashMap);

        // 1.输出编号为10000000的人
        String value = hashMap.get(10000000);
        System.out.println(value);

        // 2.删除编号10000001的人
        hashMap.remove(10000001);
        System.out.println(hashMap);

        // 3.是否包含编号为10000002的人与叫Fuck的人
        System.out.println(hashMap.containsKey(10000002));
        System.out.println(hashMap.containsValue("Fuck"));

        // 4.替换编号为10000003的人的名字为Dog
        hashMap.replace(10000003,"Dog");
        System.out.println(hashMap);

        // 5.保存编号
        Set<Integer> keys = hashMap.keySet();
        System.out.println(keys);

        // 6.保存编号与名字
        Set<Map.Entry<Integer, String>> entrySet = hashMap.entrySet();
        System.out.println(entrySet);

    }

已经存在的键值对,再次.put()会替换原来的,.get()不存在的值会返回null?

十二.?Entry与Map转换Set之后遍历: Iterator<Entry<Integer,Integer>> iterator = entrySet.iterator();?

  • 之所以使用Entry把Map转换Set是因为之后方便遍历
  • Entry就是用来管理键值对对象的,将对象包裹起来,提供遍历的方式
  • Entry可以使用迭代器,筛选值,但只适合在内存中使用,不适用于JDBC
  public void MapTest() {

        HashMap<Integer,Integer> hashMap = new HashMap<>();

        System.out.println("学生准考证号与成绩");

        hashMap.put(10000000,88);
        hashMap.put(10000001,49);
        hashMap.put(10000002,53);
        hashMap.put(10000003,83);
        hashMap.put(10000004,71);

        System.out.println(hashMap);

        System.out.println("80分以上的分数");
        // 使用Set保存学生准考证号与成绩方便遍历
        Set<Map.Entry<Integer,Integer>> entrySet = hashMap.entrySet();
        // 使用ArrayList保存80分以上的分数
        ArrayList<Integer> arrayList = new ArrayList<>();

        // 迭代器的泛型是Map.Entry<Integer,Integer>不要出错
        Iterator<Map.Entry<Integer,Integer>> iterator = entrySet.iterator();

        while (iterator.hasNext()) {
            // 取出学生成绩放入vaLue
            int value = iterator.next().getValue();
            // 判断80分以上的分数
            if (value > 80) {
               arrayList.add(value);
            }
        }
        System.out.println(arrayList);
    }

?

?十三.LinkedHashMap

HashMap是无序的,可以自定义泛型,而LinkedHashMap相当于有序的HashMap?

LinkedHashMap (Java Platform SE 8 ) (oracle.com)?

?

十四.集合框架部分结束?

剩下的类需要自己去学习了!了解各类是怎么实现的,以及其之间的区别,JDK的新特性暂时用不到,还没学习到框架?

文章来源:https://blog.csdn.net/2301_76556912/article/details/135134299
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。