• Java 集合---尚硅谷Java入门视频学习


    • 问题:什么时候需要一个容纳数据的容器,也就是集合对象?
      Java集合框架中就包含了对不确定个数的数据处理的集合类
    • 问题:如果只是为了容纳数据,可以是直接使用数组,为什么要学习集合?
      数组使用起来不方便。在数据个数不确定的场合,数组使用起来不是很方便

    总结:对不确定的有关系的数据进行相同的逻辑处理的场合,使用集合是一个不错的选择

    根据数据的不同,Java的集合分为2大体系:

      1. 单一数据体系 : Collection接口定义了相关的规则
        常用的子接口

    List :按照插入顺序保存数据,数据可以重复的
    具体的实现类: ArrayList, LinkedList
    Set : 集,无序保存,数据不能重复
    具体的实现类 HashSet
    Queue : 队列
    具体的实现类:ArrayBlockingQueue

      1. 成对出现的数据体系 : Map接口定义了相关的规则
        所谓的成对的数据,就是2个数据有关系,可以根据第一个数据关联到第二个数据。
        也称之为键值对数据 ,(123123, zhangsan) => (key, value)

    具体的实现 : HashMap, Hashtable

    1.ArrayList

    创建第一个集合对象:ArrayList

     ArrayList list = new ArrayList(3);
    
    • 1
    1. 不需要传递构造参数,直接new就可以,底层数组为空数组
    2. 构造参数需要传递一个int类型的值,用于设定底层数组的长度
    3. 构造参数需要传递一个Collection集合类型的值,用于将其他集合中的数据放置在当前集合中
    • 增加数据
      添加数据时,如果集合中没有任何的数据,那么底层会创建长度为10的数组(扩容)
     	// add方法可以增加数据,只要将数据作为参数传递到add方法即可
        // 添加数据时,如果集合中没有任何的数据,那么底层会创建长度为10的数组
        list.add("zhangsan");
        list.add("zhangsan");
        list.add("wangwu");
        list.add("zhaoliu");
        // 获取集合中数据的条数
        System.out.println(list.size());
        // 获取指定位置的数据,可以采用索引的方式
        System.out.println(list.get(1));
        // 遍历集合中的数据
        for ( int i = 0; i < list.size(); i++ ) {
            //System.out.println("集合中的数据:" + list.get(i));
        }
        // TODO 如果循环遍历集合数据时,不关心数据的位置,那么可以采用特殊的for循环
        // for (循环对象:集合) {}
        for ( Object obj : list ) {
            System.out.println("集合中的数据:" + obj);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    // add方法可以传递2个参数的,第一个参数表示数据增加的位置(索引),第二个参数表示数据
    list.add(1, "zhaoliu");
    
    • 1
    • 2

    addAll()方法

    		ArrayList list = new ArrayList();
            list.add("zhangsan");
            list.add("lisi");
            list.add("wangwu");
            list.add("zhangsan");
            list.add("zhangsan");
            ArrayList otherList = new ArrayList();
            otherList.add("1");
            otherList.add("2");
            otherList.add("3");
            list.addAll( otherList );//将otherList 集合追加到list集合末尾
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 修改数据
      将指定位置的数据进行修改,set方法需要传递2个参数,第一个参数表示数据的位置,第二个参数修改的值。
      方法会返回结果,这个结果就是更新前的值
    Object oldVal = list.set(1, "lisi");
    System.out.println("修改前的值:" + oldVal);
    
    • 1
    • 2
    • 删除数据
      将指定位置的数据进行删除,remove方法需要传递1个参数,参数表示数据的位置。
      方法会返回结果,这个结果就是删除的值
    Object removeVal = list.remove(1);
    System.out.println("删除的值:" + removeVal);
    // TODO 打印集合对象
    System.out.println(list);
    
    • 1
    • 2
    • 3
    • 4
    • 其他常用方法
    // size方法表示集合内部数据的数量
    System.out.println(list.size());
    // 清空集合中的数据
    list.clear();
    // 删除指定集合中的数据
    list.removeAll(otherList);  //删除list集合中otherList集合里的数据
    // 判断集合中的数据是否为空
    System.out.println(list.isEmpty());
    // 用于判断集合中是否存在某条数据,返回布尔类型的值
    System.out.println(list.contains("zhangsan123"));
    // 用于获取数据在索引中的第一个位置,如果数据不存在,那么返回-1
    System.out.println(list.indexOf("zhangsan123"));
    System.out.println(list.indexOf("zhangsan"));
    System.out.println(list.lastIndexOf("zhangsan"));
    //集合变数组
    Object[] objects = list.toArray();
    // 复制新集合
    Object clone = list.clone();
    ArrayList list1 = (ArrayList)clone;
    System.out.println(list);
    System.out.println(list1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2.LinkedList

    在这里插入图片描述

    • 构建集合对象
      LinkedList list = new LinkedList();
    
    • 1
    • 添加数据
    //添加数据
    // 增加第一个数据
    list.add("zhangsan");
    list.add("lisi");
    list.add("wangwu");
    //向指定的位置添加数据 
    list.addFirst("lisi"); //增加到数据的前面
    list.addLast("2");//增加到数据的后面(默认)
    list.add(1, "wangwu"); //添加到第一个位置(0和1之间)
    //向集合中添加另一个集合
    LinkedList list1 = new LinkedList();
    list1.add("zhangsan1");
    list1.add("lisi2");
    list1.add("wangwu3");
    list.addAll(list1);  //将list1集合追加到list集合末尾
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 获取数据
    System.out.println(list.getFirst());
    System.out.println(list.getLast());
    // 获取数据(遍历数据)
    System.out.println(list.get(1));
    for ( int i = 0; i < list.size(); i++ ) {
        System.out.println(list.get(i));
    }
    for ( Object obj : list ) {
       System.out.println(obj);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 修改数据
    list.set(1, "zhaoliu");
    
    • 1
    • 删除数据
       list.remove("zhangsan");
       list.removeFirst(); // 删除第一个
       list.removeLast(); // 删除最后一个
       list.remove(1);// 删除指定索引
    
    • 1
    • 2
    • 3
    • 4
    • 其他方法
    System.out.println(list.size());
    System.out.println(list.isEmpty());
    list.clear();
    list.contains("1");
    list.element(); // 获取集合第一个数据
    list.indexOf("");
    list.lastIndexOf("");
    list.push("aaa"); // 添加数据到第一个
    System.out.println(list.pop()); // 弹出第一个数据
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ArrayList和LinkedList对比

    在这里插入图片描述

    3.泛型

    背景

    public class Main{
        public static void main(String[] args) {
            Person6 person = new Person6();
            User6 user = new User6();
    		ArrayList list = new ArrayList();
            list.add(person);
          	list.add(user);
            list.remove(0);
            // 从集合中获取的对象类型为Object
            Object o = list.get(0);
            // 如果想要执行对象的方法,那么需要进行强制类型转换
           if ( o instanceof  Person6 ) {
                Person6 p = (Person6)o;
                p.testPerson();
           }
        }
    }
    class Person6 {
        public void testPerson() {
            System.out.println("person...");
        }
    }
    class User6 {
        public void testUser() {
            System.out.println("user...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    因为多态语法对对象的使用场景进行了约束,从集合中获取的对象类型为Object,不能直接调用对象类型本身的方法,可见集合对象在处理不同类型的数据时比较繁琐。
    集合中没有约定存储数据的类型,不同类型的数据都可以存放在里面,保存了不同类型的数据后,处理起来机会比较麻烦。
    在这里插入图片描述
    在这里插入图片描述

    泛型的使用

    泛型和类型
    在这里插入图片描述
    类型相当于一个容器类,可以是集合,也可以是其他类

    public class Java07_Collection_Generic {
        public static void main(String[] args) {
            // 泛型语法
            // TODO 泛型和类型的区别
            // 有时,也把泛型称之为类型参数
            MyContainer<User7> myContainer = new MyContainer();
            //myContainer.data = new Object();
    
            // 类型存在多态的使用方式,但是泛型没有多态的概念
            test(myContainer);
    
    
        }
        public static void test(MyContainer<User7> myContainer) {
            System.out.println(myContainer);
        }
    }
    // TODO 容器类
    class MyContainer<T> {
        public T data;
    }
    class User7 {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4.HashSet

    • 创建对象
     // HashSet : Hash + Set
    // Hash : 哈希算法,散列算法
    HashSet set = new HashSet();
    
    • 1
    • 2
    • 3
    • 增加数据
      不会重复存储
    // TODo 增加数据
    set.add("zhangsan");
    set.add("zhangsan");  
    set.add("lisi");
    set.add("wangwu");  //[zhangsan,lisi,wangwu]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不能修改数据 ,要修改只能先删除再增加。

    • 删除数据
    //删除数据
    set.remove("wangwu");
    
    • 1
    • 2
    • 查询数据
      数据没有对应的索引,没有查询数据的方法。要查询只能遍历
    // TODo 查询数据
    for (Object o : set) {
       System.out.println(o);
    }
    System.out.println(set);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 其他常用方法
    HashSet set = new HashSet();
    ArrayList list = new ArrayList();
    list.add("zhangsan");
    list.add("lisi");
    list.add("wamngwu");
    set.addAll(list);
    Object[] objects = set.toArray();
    System.out.println(set.isEmpty());
    set.clear();
    set.contains("zhangsan");
    System.out.println(set.size());
    Object clone = set.clone();
    System.out.println(clone);
    System.out.println(set);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 重复数据的问题
    public class Java09_Collection_Set_2 {
        public static void main(String[] args) {
    
            
            HashSet set = new HashSet();
    
            User9 user1 = new User9();
            user1.id = 1001;
            user1.name = "zhangsan";
            System.out.println(user1.hashCode());
    
            User9 user2 = new User9();
            user2.id = 1001;
            user2.name = "zhangsan";
            System.out.println(user2.hashCode());
    
            User9 user3 = new User9();
            user3.id = 1002;
            user3.name = "lisi";
    
            set.add(user1);
            set.add(user2);
            set.add(user3);
            System.out.println(set);
        }
    }
    class User9 {
        public int id;
        public String name;
        @Override
        public String toString() {
            return "User["+id+", "+name+"]";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    HashSet中不会有重复的数据,上面的例子中,user1和user2对象虽然属性值相同,但其内存地址不同,在内存中是独立保存的,是两个不同的对象,因此上面的HashSet中存储的是三个对象。

    传递给HashSet一个对象时,进行定位操作的方式:传递一个对象时,以对象的hashCode来做哈希运算,找到数据存放的位置。如果这个位置没有存放数据,则直接将数据存储,如果这个位置已经有数据,则通过equals()方法判断两个数据是否相等,如果相等,则直接丢弃即将要存入的数据;如果不相等,则通过链表将两个位置相同的数据连接起来进行存放(HashSet 底层数据结构为 数组 + 链表)。
    如果要使HashSet以对象的属性值是否相同为标准,判断存入的两个对象是否相同,则需要将判断对象是否相等以及获取对象hashCode值的方法进行重写。

    public class Java09_Collection_Set_2 {
        public static void main(String[] args) {
    
            // TODO 集合 - Collection - Set
            // HashSet 底层数据结构为 数组 + 链表
    
            HashSet set = new HashSet();
            User9 user1 = new User9();
            user1.id = 1001;
            user1.name = "zhangsan";
            System.out.println(user1.hashCode());
    
            User9 user2 = new User9();
            user2.id = 1001;
            user2.name = "zhangsan";
            System.out.println(user2.hashCode());
    
            User9 user3 = new User9();
            user3.id = 1002;
            user3.name = "lisi";
    
            set.add(user1);
            set.add(user2);
            set.add(user3);
            System.out.println(set);
        }
    }
    class User9 {
        public int id;
        public String name;
    
        @Override
        // 类似于内存地址
        public int hashCode() {
            return id;
        }
    
        @Override
        // 判断两个对象的属性是否完全相同
        public boolean equals(Object obj) {
            if ( obj instanceof User9 ) {
                User9 otherUser = (User9)obj;
                if ( otherUser.id == this.id ) {
                    if ( otherUser.name.equals(this.name) ) {
                        return true;
                    }
                }
                return false;
            } else {
                return false;
            }
        }
        @Override
        public String toString() {
            return "User["+id+", "+name+"]";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    如此,两个对象id值相同时,其hashCode值相同,进行哈希定位时其位置也相同;再根据重写的equals方法,可判断出两个对象属性完全相同,即两个数据为同一个值。因此上面的HashSet中只会存储两个对象。

    5.Queue

    • 入队方法
    // ArrayBlockingQueue : Array + Blocking(阻塞,堵住) + Queue
    ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
    // add方法如果增加数据增加不了,直接发生错误。
    queue.add("zhangsan");
    queue.add("lisi");
    queue.add("wangwu");
    queue.add("zhaoliu"); // 发生错误,Queue full
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    queue.put("zhangsan");
    System.out.println("第一个人挂号");
    queue.put("lisi");
    System.out.println("第二个人挂号");
    queue.put("wangwu");
    System.out.println("第三个人挂号");
    queue.put("zhaoliu");  // 不发生错误,但一直阻塞
    System.out.println("第四个人挂号");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    boolean zhangsan = queue.offer("zhangsan");
    System.out.println(zhangsan);   // true
    boolean lisi = queue.offer("lisi");
    System.out.println(lisi);
    boolean wangwu = queue.offer("wangwu");
    System.out.println(wangwu);
    boolean zhaoliu = queue.offer("zhaoliu");
    System.out.println(zhaoliu);  // false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 出队方法
    System.out.println(queue.poll());  // zhangsan
    //当队列中没有数据时,执行此方法会输出null
    
    • 1
    • 2
    System.out.println(queue.take());// zhangsan
    //当队列中没有数据时,执行此方法会阻塞程序
    
    • 1
    • 2

    6. HashMap

    在这里插入图片描述
    存储原理:根据key,由Hash算法计算存储的位置,可以不能重复,重复则覆盖

    // HashMap : Hash + Map
    // 数据存储是无序
    HashMap map = new HashMap();
     // 添加数据:put
    // 修改数据,put方法也可以修改数据,返回值就是被修改的值
    map.put("zhangsan", "1");
    System.out.println(map.put("zhangsan", "4"));  //key相同,value会被覆盖   输出覆盖的值 1
    map.put("lisi", "2");
    map.put("wangwu", "3");
    // 修改数据 返回值就是被修改的值   如果不存在则返回null,且不会在map中添加
    Object b = map.replace("b", "4"); 
    System.out.println(b);
     //查询数据
    System.out.println(map.get("zhangsan"));
    // 删除数据
    map.remove("zhangsan");
    System.out.println(map);
    map.remove("zhangsan", "1");  //删除键值对 key value都相同时才删除
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    // TODO 获取map集合中所有的key
    Set set = map.keySet();
    for (Object k : set) {
       System.out.println(map.get(k));  //获取key对应的value
    }
    System.out.println(map.containsKey("zhangsan"));
    Collection values = map.values();
    map.containsValue("1");
    System.out.println(map);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    HashMap<String, String> map = new HashMap();
    // TODO 获取键值对对象
    Set<Map.Entry<String, String>> entries = map.entrySet();
    for (Map.Entry<String, String> entry : entries) {
       System.out.println(entry.getKey() + "=" + entry.getValue()); //lisi=2
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7.Hashtable

    HashMap与Hashtable

    1. 实现方式不一样的 : 继承父类不一样
    2. 底层结构的容量不同: HashMap(16), Hashtable(11)
    3. HashMap的K,V都可以为null, Hashtable的K, V不能是null
    4. HashMap的数据定位采用的是Hash算法,但是Hashtable采用的就是hashcode
    5. HashMap的性能较高,但是Hashtable较低

    8.迭代器

    HashMap<String, Integer> map = new HashMap<String, Integer>();
    map.put("a", 1);
    map.put("b", 2);
    map.put("c", 3);
    Set<String> keys = map.keySet();
    for (String key : keys) {
        if ( "b".equals(key) ) {
    	    map.remove("b");
        }
       System.out.println(map.get(key));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在遍历的时候修改会发生错误ConcurrentModificationException

    // TODO 迭代器
            Iterator<String> iterator = keys.iterator();
            // hasNext方法用于判断是否存在下一条数据
            while (iterator.hasNext()) {
                // 获取下一条数据
                String key = iterator.next();
                if("b".equals(key)) {
                    // remove方法只能对当前数据删除
                    iterator.remove();
                }
                System.out.println(map.get(key));
            }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    Java 常用API的运用,效率及技巧
    Vue 先初始化父组件再初始化子组件的方法(自定义父子组件mounted执行顺序)
    智能物流新纪元:分布式I/O模块重塑仓储自动化
    【mysql】—— 函数的基本介绍
    阿里云服务结构--长期更新
    手机上的动态ip流量是算自己的流量吗?
    C#学习系列相关之多线程(一)----常用多线程方法总结
    流水线上的农民:我在工厂种蔬菜
    基于ssm宠物医院管理系统获取(java毕业设计)
    在typora中利用正则表达式,批量处理图片
  • 原文地址:https://blog.csdn.net/Monstar_ViCtory/article/details/127915507