美文网首页
Java集合的用法及特点

Java集合的用法及特点

作者: 魏皇子 | 来源:发表于2020-05-16 19:40 被阅读0次

    单列LIst集合

    单列列表集合:

    • 集合的由来
      长度是固定的,当添加的元素超过了多个的长度时需要对分段重新定义,太麻烦了,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,通过元素的增加而增加,通过元素的减少而减少

    副本和集合的区别:

    区别1:

    #数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值  
    
    集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但在存储的时候会自动装箱变成对象
    

    区别2:

    分布长度是固定的,不能自动增长*集合的长度的是可变的,可以根据元素的增加而增长1 2 3 C:复制和集合什么时候用
    

    数组和集合什么时候用:

    1. 如果元素个数是固定的推荐用堆叠

    2. 如果元素个数不是固定的推荐用集合

    Collection集合的基本功能用法

    public static void main(String[] args) {
        Collection c = new ArrayList();    //创建集合对象
        c.add("a");       //添加元素,返回值为boolean
        c.remove("a");    //删除元素,返回值为boolean
        c.clear();        //清空集合,无返回值
        boolean pd = c.contains("a");   //判断是否包含元素,包含则返回true
        boolean pd = c.isEmpty();        //判断集合是否为空,为空返回true
        int num = c.size();            //获取集合中元素的个数,返回值为int
    }
    

    Collection集合的带All功能用法

    public static void main(String[] args) {
        Collection c1 = new ArrayList();
        c1.add("a");
        c1.add("b");
        c1.add("c");
        c1.add("d");
    
        Collection c2 = new ArrayList();
        c2.addAll(c1);      //c1全部赋值给c2集合
        c1.removeAll(c2);   //删除c1内与c2交集的部分,返回值为boolean
        boolean b = c1.containsAll(c2);//判断调用的集合是否包含传入的集合
        boolean c = c1.retainAll(c2);//取c1和c2的交集,存入c1
        //如果调用的集合改变就返回true,注意:如果c2无值则c1也将变为无值
        System.out.println(c1);
        System.out.println(c2);
    }
    

    集合的遍历之集合转数组遍历

    public static void main(String[] args) {
        Collection c = new ArrayList();    //创建集合对象
        c.add("a");       
        c.add("b");    
        c.add(new Student("王欢", 28));    //创建对象存入数组
       
        Object[] arr = c.toArray();     //将集合转换为数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        
    }
    

    集合的遍历之迭代器遍历

    public static void main(String[] args) {
        Collection c1 = new ArrayList();
        c1.add("a");
        c1.add("b");
        c1.add("c");
        c1.add("d");
    
        Iterator it = c1.iterator();//获取c1集合的迭代器
        while (it.hasNext()) {  //判断集合中是否有元素
            System.out.println(it.next());  //获取元素
        }
    
        Collection c2 = new ArrayList();
        c2.add(new Student("张三", 23));
        c2.add(new Student("李四", 18));
    
        Iterator it2 = c2.iterator();//获取c2集合的迭代器
        while (it2.hasNext()) {
            Student s = (Student)it2.next();    //向下转型
            System.out.println(s.getName());
        }
    
    }
    

    List集合的特有功能

    public static void main(String[] args) {
        List c1 = new ArrayList();
        c1.add("a");
        c1.add("b");
        c1.add("c");
        c1.add("d");
    
        c1.add(1, "e");//指定索引位置添加元素
        Object obj = c1.remove(1);//通过索引删除元素并返回删除的元素
        Object obj2 = c1.get(0);    //通过索引获取指定元素
        c1.set(0, "z");         //将指定位置的元素修改
        System.out.println(obj2);
        System.out.println(c1);
    
    }
    

    List集合特有迭代器

    该迭代器可以在遍历的同时向集合内添加元素

    public static void main(String[] args) {
        List c1 = new ArrayList();
        c1.add("a");
        c1.add("b");
        c1.add("nan");
        c1.add("c");
        c1.add("d");
    
        ListIterator it = c1.listIterator();//List集合特有迭代器
        while (it.hasNext()) {
            String str = (String) it.next();
            if ("nan".equals(str)) {    //当集合中存在nan时则添加元素
                it.add("zzzzzzz");      //通过迭代器添加元素
            }
        }
        System.out.println(c1);
    
    }
    

    Vector的特有功能概述和测试【注意:Vector已被完全替代,请勿再使用】

    public static void main(String[] args) {
        Vector v = new Vector();
        v.addElement("a");
        v.addElement("b");
        v.addElement("c");
        v.addElement("d");
    
        Enumeration en = v.elements();//获取枚举
        while (en.hasMoreElements()) {//判断集合中是否有元素
            System.out.println(en.nextElement());//获取集合中的元素
        }
    }
    

    List的三个子类的特点

    ArrayList:

    
    底层数据结构是数组,查询快,增删慢。
    
    线程不安全,效率高。
    

    Vector:

    底层数据结构是数组,查询快,增删慢。
    
    线程安全,效率低。
    

    Vector相对ArrayList查询慢(线程安全的)

    Vector相对LinkedList增删慢(数组结构)

    LinkedList:

    底层数据结构是链表,查询慢,增删快。
    
    线程不安全,效率高。
    
    Vector和ArrayList的区别
    

    Vector是线程安全的,效率低

    ArrayList是线程不安全的,效率高

    共同点:都是数组实现的
    
    ArrayList和LinkedList的区别
    

    ArrayList底层是数组结果,查询和修改快

    LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢

    共同点:都是线程不安全的

    注意:线程不安全可以通过工具类改为安全的

    
    如何选择:
    

    查询多用ArrayList

    增删多用LinkedList

    如果都多ArrayList

    #### 案例:ArrayList去除集合中字符串的重复值
    ```java
    public class CeShi {
        public static void main(String[] args) {
            ArrayList list = new ArrayList();
            list.add("a");
            list.add("a");
            list.add("b");
            list.add("b");
    
            ArrayList abc = JiHeFF(list);
            System.out.println(abc);
        }
    
        public static ArrayList JiHeFF(ArrayList list) {
            ArrayList newList = new ArrayList();    //创建一个新集合
            Iterator it = list.iterator();          //获取迭代器
    
            while (it.hasNext()) {        //判断老集合中是否有元素,遍历老集合
                Object obj = it.next();  //将每一个元素临时记录住
                if (!newList.contains(obj)) {   //如果新集合中不包含该元素
                    newList.add(obj);       //将该元素添加到新集合中
                }
            }
            return newList;     //将新集合返回
        }
    }
    

    案例:ArrayList去除集合重复自定义对象元素

    注意:需要重写类的equals()方法

    public class CeShi {
        public static void main(String[] args) {
            ArrayList list = new ArrayList();
            list.add(new Student("张三", 23));
            list.add(new Student("张三", 23));
            list.add(new Student("李四", 23));
            list.add(new Student("李四", 23));
            list.add(new Student("李四", 23));
    
            ArrayList newList = JiHeFF(list);
            System.out.println(newList);
        }
    
        public static ArrayList JiHeFF(ArrayList list) {
            ArrayList newList = new ArrayList();    //创建一个新集合
            Iterator it = list.iterator();          //获取迭代器
    
            while (it.hasNext()) {        //判断老集合中是否有元素,遍历老集合
                Object obj = it.next();  //将每一个元素临时记录住
                if (!newList.contains(obj)) {   //如果新集合中不包含该元素
                    newList.add(obj);       //将该元素添加到新集合中
                }
            }
            return newList;     //将新集合返回
        }
    }
    
    //重写Student类的equals()方法,可以通过IDEA快速生成
    @Override
    public boolean equals(Object o) {
        Student s = (Student) o;
        return this.name.equals(s.name) && this.age == s.age;
    }
    

    案例:ArrayList通过迭代器获取自定义对象指定属性值

    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<Person>();
        list.add(new Person("张三", 23));
        list.add(new Person("李四", 24));
            
        Iterator<Person> it = list.iterator();    //获取迭代器
        while(it.hasNext()) {
            //System.out.println(it.next().getName() + "..." + it.next().getAge());//next方法只能调用一次,如果调用多次会将指针向后移动多次
            Person p = it.next();    //声明对象并将数据存入           
            System.out.println(p.getName() + "..." + p.getAge());    //打印所需要的属性
        }
    }
    

    LinkedList的特有功能

    public static void main(String[] args) {
            LinkedList list = new LinkedList();
            list.addFirst("a"); //往头添加元素
            list.addFirst("b");
            list.addFirst("c");
            list.addFirst("d");
            list.addLast("e");  //往尾添加元素
            
            //System.out.println(list.getFirst());//获取第一个
            //System.out.println(list.getLast());//获取最后一个
            //System.out.println(list.removeFirst());//删除第一个
            //System.out.println(list.removeLast());//删除最后一个
            
            System.out.println(list.get(1));//获取索引位置的元素,其实并不是靠索引,因为是链表结构,靠的是挨个查询
            System.out.println(list);
        }
    

    增强for的功能概述和测试(foreach)

    • A:增强for概述

      • 简化数组和Collection集合的遍历
    • B:格式:

      • for(元素数据类型 变量 : 数组或者Collection集合) {使用变量即可,该变量就是元素}
    • C:案例演示

      • 数组,集合存储元素用增强for遍历
    • D:好处

    简化遍历

    增强for循环底层依赖的是迭代器(Iterator)

    //增强for功能演示
    public class CeShi {
        public static void main(String[] args) {
            ArrayList<Student> list1 = new ArrayList<>();
            list1.add(new Student("张三", 23));
            list1.add(new Student("张三", 23));
            list1.add(new Student("李四", 23));
            list1.add(new Student("李四", 23));
            list1.add(new Student("李四", 23));
            for (Student i : list1) {
                Student s1 = i;
                System.out.println(i.getName());
            }
            System.out.println("==============================");
            int[] arr = {11, 22, 33, 44, 55};
            for (int i : arr) {
                System.out.println(i);
            }
        }
    }
    

    集合元素的三种删除方式测试

    • 普通for循环,可以删除,但是索引要–

    • 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常

    增强for循环不能删除

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("d");
            
        //1,普通for循环删除,索引要--
        /*for(int i = 0; i < list.size(); i++) {
            if("b".equals(list.get(i))) {
                list.remove(i--);                           //通过索引删除元素
            }
        }*/
            
        //2,迭代器删除
        /*Iterator<String> it = list.iterator();
        while(it.hasNext()) {
            if("b".equals(it.next())) {
                //list.remove("b");                         //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
                it.remove();
            }
        }*/
            
        /*for(Iterator<String> it2 = list.iterator(); it2.hasNext();) {
            if("b".equals(it2.next())) {
                //list.remove("b");                         //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
                it2.remove();
            }
        }*/
        //3,增强for循环,增强for循环不能删除,只能遍历
        for (String string : list) {
            if("b".equals(string)) {
                list.remove("b");
            }
        }
        System.out.println(list);
    }
    

    单列Set集合:

    //Set集合,无索引,不可以重复,无序(存取不一致)
    //注意:存储类对象则需要修改类对象的equals和hashCode方法,否则可以存储重复对象
    //定义HashSet
    HashSet<Student> hs = new HashSet<>();
    hs.add(new Student("张三", 23));
    
    //定义LinkedHashSet,底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
    LinkedHashSet<String> lhs = new LinkedHashSet<>();
    lhs.add("a");
    
    //定义TreeSet,用来对象元素进行排序,同样他也可以保证元素的唯一
    TreeSet<Integer> ts = new TreeSet<>();
    ts.add(3);
    

    双列Map集合:

    • Map接口和Collection接口的不同

    • Map是双列的,Collection是单列的

    • Map的键唯一,Collection的子体系Set是唯一的

    • Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

    A:Map集合的功能概述

    • a:添加功能

    • V put(K key,V value):添加元素。

    • 如果键是第一次存储,就直接存储元素,返回null

    • 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

    • b:删除功能

    • void clear():移除所有的键值对元素

    • V remove(Object key):根据键删除键值对元素,并把值返回

    • c:判断功能

    • boolean containsKey(Object key):判断集合是否包含指定的键

    • boolean containsValue(Object value):判断集合是否包含指定的值

    • boolean isEmpty():判断集合是否为空

    • d:获取功能

    • Set<Map.Entry<K,V>> entrySet():

    • V get(Object key):根据键获取值

    • Set keySet():获取集合中所有键的集合

    • Collection values():获取集合中所有值的集合

    • e:长度功能

    • int size():返回集合中的键值对的个数

    Map<String, Integer> map = new HashMap<>();
    Integer i1 = map.put("张三", 23);//添加
    Integer value = map.remove("张三");   //根据键删除元素,返回键对应的值
    System.out.println(map.containsKey("张三"));      //判断是否包含传入的键
    System.out.println(map.containsValue(100));     //判断是否包含传入的值
    

    第一种迭代方式

    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("张三", 23);
        map.put("李四", 24);
        map.put("王五", 25);
        map.put("赵六", 26);
    
        Integer i = map.get("张三");   //根据键获取值
    
        //获取所有的键
        Set<String> keySet = map.keySet();  //获取所有键的集合
        Iterator<String> it = keySet.iterator();//获取迭代器
        while (it.hasNext()) {
            String key = it.next(); //获取每一个键
            Integer value = map.get(key);//根据键获取值
            System.out.println(key + "=" + value);
        }
        System.out.println("=======================================");
        //使用增强for循环遍历
        for (String key : map.keySet()) {            //map.keySet()是所有键的集合
            System.out.println(key + "=" + map.get(key));
        }
    }
    

    第二种迭代方式

    /**
         * Map集合的第二种迭代,根据键值对对象,获取键和值
         *  A:键值对对象找键和值思路:
            * 获取所有键值对对象的集合
            * 遍历键值对对象的集合,获取到每一个键值对对象
            * 根据键值对对象找键和值
         */
        public static void main(String[] args) {
            Map<String, Integer> map = new HashMap<>();
            map.put("张三", 23);
            map.put("李四", 24);
            map.put("王五", 25);
            map.put("赵六", 26);
            
            //Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
            /*Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
            //获取每一个对象
            Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
            while(it.hasNext()) {
                //获取每一个Entry对象
                Map.Entry<String, Integer> en = it.next();  //父类引用指向子类对象
                //Entry<String, Integer> en = it.next();    //直接获取的是子类对象
                String key = en.getKey();                   //根据键值对对象获取键
                Integer value = en.getValue();              //根据键值对对象获取值
                System.out.println(key + "=" + value);
            }*/
            
            for(Entry<String, Integer> en : map.entrySet()) {
                System.out.println(en.getKey() + "=" + en.getValue());
            }
        }
    

    案例:用HashMap统计字符串中每个字符出现的次数

    public class CeShi {
        public static void main(String[] args) {
            //1,定义一个需要被统计字符的字符串
            String s = "abbccddddddcccbbaa";
            //2,将字符串转换为字符数组
            char[] arr = s.toCharArray();
            //3,定义双列集合,存储字符串中字符以及字符出现的次数
            HashMap<Character, Integer> hm = new HashMap<>();
            //4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
            for (char c : arr) {
                //5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
                /*if (!hm.containsKey(c)) {//如果不包含这个键
                    hm.put(c, 1);
                } else {
                    hm.put(c, hm.get(c) + 1);
                } */
                hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
            }
            //6,打印双列集合获取字符出现的次数
            for (Character key : hm.keySet()) {             //hm.keySet()代表所有键的集合
                System.out.println(key + "=" + hm.get(key));//hm.get(key)根据键获取值
            }
        }
    }
    

    集合总结:

    Collection(单列集合)

    List(存取有序,有索引,可以重复)
    
        ArrayList
    
            底层是数组实现的,线程不安全,查找和修改快,增和删比较慢
    
          LinkedList
    
               底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
        Vector
               底层是数组实现的,线程安全的,无论增删改查都慢
    
            * 如果查找和修改多,用ArrayList
    
            * 如果增和删多,用LinkedList
    
            * 如果都多,用ArrayList
    
     Set(存取无序,无索引,不可以重复)
    
        HashSet
    
            底层是哈希算法实现
    
            LinkedHashSet
    
                底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样
        TreeSet
                底层是二叉树算法实现
    
           *一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高
    
           * TreeSet在面试的时候比较多,问你有几种排序方式,和几种排序方式的区别
    

    Map(双列集合)

    HashMap
          底层是哈希算法,针对键
    
        LinkedHashMap
    
                底层是链表,针对键
    
    TreeMap
    
          底层是二叉树算法,针对键
    
      *开发中用HashMap比较多
    

    相关文章

      网友评论

          本文标题:Java集合的用法及特点

          本文链接:https://www.haomeiwen.com/subject/czirohtx.html