• java基础12—集合类


    集合类


    参考资料:《Java从入门到精通》/明日科技编著. 4版. 北京:清华大学出版社,2016

    一、集合类概述

    java.util包中提供了一些集合类,这些集合类又被称为容器。提到集合类不得不想到数组,集合与数组的区别如下:

    • 数组用来存放基本类型的数组,集合用来存放对象的引用
    • 数组的长度是固定的,集合的长度是可变的。

    常见的集合有List集合、Set集合和Map集合,其中List集合与Set集合继承了Collection接口,各接口还提供了不同的实现类。

    上述集合类的继承关系如下所示:

    graph LR
    Map --> Java.lang.Object
    Set --Collention --> Java.lang.Object
    List --Collention --> Java.lang.Object
    

    二、Collection接口

    • Collection接口是层次结构中的根接口
    • 构成Collection的单元称为元素
    • Collection接口通常不能直接使用,但是该接口提供了添加元素、删除元素和管理数据的方法。

    Collection接口常用的方法如下所示:

    方法 功能描述
    add(E e) 将指定对象添加到集合中
    remove(Object o) 将指定的对象从集合中删除
    isEmpty() 判断当前集合是否为空,返回boolean值
    iterator() 迭代器,用于遍历集合中的对象
    size() 获取该集合中元素的个数,返回int值
    import java.util.*;    //导入java.util包
    
    public class Muster {
        public static void main(String[] args) {
            //实例化集合对象
            Collection<String> list = new ArrayList<>();
            //向集合添加元素
            list.add("abc");
            list.add("def");
            //创建迭代器
            Iterator<String> it = list.iterator();
            //判断是否有下一个元素,遍历集合中的元素
            while (it.hasNext()){
                String str = (String) it.next();
                System.out.println(str);
            }
        }
    }
    
    运行结果:
    abc
    def
    

    注意:Iterator的next()方法返回的是Object类型。

    三、List集合

    • List集合包括List接口和List接口的所有实现类。
    • List集合中的元素是允许重复的。
    • List集合中元素的顺序就是对象插入的顺序
    • 类似Java数组,List集合可以通过索引来访问集合中的元素。

    1、List接口

    List接口继承了Collection接口,因此包含了Collection接口中的所有方法。此外,List接口还单独定义了两个非常重要的方法,如下所示:

    • get( int index ):获得指定索引位置的元素;
    • set( int index, Object obj):将集合中指定索引位置的对象修改为指定的对象。

    2、List接口的实现类型

    List接口的常用实现类有ArrayList和LinkedList。

    1. ArrayList类
    • 优点:实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问。
    • 缺点:向指定的索引位置插入对象或删除对象的速度较慢。
    1. LinkedList类
    • 优点:采用链表结构保存对象,便于向集合中插入和删除对象,所以需要向集合中插入、删除对象时,使用LinkedList类实现的List集合的效率比较高。
    • 缺点:对于随机访问集合中的对象,使用LinkedList类实现List集合的效率比较低。

    下面分别通过ArrayList类和LinkedList类实例化List集合:

    List <E> list1 = new ArrayList<>();
    List <E> list2 = new LinkedList<>();
    

    上述代码中,E是指的合法的Java数据类型。例如,如果集合中的元素为字符串类型,那么E可以修改为String。

    import java.util.ArrayList;
    import java.util.List;
    
    public class Gather {
        public static void main(String[] args) {
            //实例化集合对象,设置元素为字符串类型
            List <String> list1 = new ArrayList<>();
            //向集合中添加对象
            list1.add("hello");
            list1.add("world");
            list1.add("xuliang");
            list1.add("xuliang");    //List集合允许元素重复
            //获取集合的长度
            System.out.println("集合的长度为:" + list1.size());
            //遍历集合的元素,元素的顺序就是对象插入集合的顺序
            for (int i = 0; i < list1.size(); i++) {
                System.out.println(list1.get(i));
            }
            
            System.out.println("-----------------");
            //修改指定索引位置的元素
            list1.set(2, "happy");
            //再次遍历集合
            for (int i = 0; i < list1.size(); i++) {
                System.out.println(list1.get(i));
            }
        }
    }
    
    运行结果:
    集合的长度为:4
    hello
    world
    xuliang
    xuliang
    -----------------
    hello
    world
    happy
    xuliang
    

    从上述代码的运行结果看,集合的索引也是从0开始,与数组一致。

    四、Set集合

    Set集合中的对象不按照特定的方式排序,只是简单地把对象加入集合,但是Set集合中不允许包含重复对象

    Set集合由Set接口和Set接口的实现类组成,Set接口继承了Collection接口,因此包含Collection接口的所有方法。

    注意:Set的构造有一个约束条件,传入的Collection对象不能有重复值,必须小心操作可变对象。

    Set接口常见的实现类有HashSet和TreeSet类。

    • HashSet类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证Set的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null元素。
    • TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此,TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。

    TreeSet集合新增的方法:

    方法 功能描述
    first() 返回Set当前第一个(最低)元素
    last() 返回Set当前第一个(最高)元素
    comparator() 返回对此Set中的元素进行排序的比较器。如果此Set采用自然排序,则返回null
    headSet(E toElement) 返回一个新的Set集合,新集合是toElement(不包含)之前的所有对象
    subSet(E fromElement) 返回一个新的Set集合,是fromElement(包含)对象与fromElement(不包含)对象之间的所有对象
    tailSet(E fromElement) 返回一个新的Set集合,新集合包含对象fromElement(包含)之后的所有对象
    import java.util.Iterator;
    import java.util.TreeSet;
    
    public class UpdateStu implements Comparable <Object>{
        String name;
        long id;
    
        public UpdateStu(String name, long id){
            this.name = name;
            this.id = id;
        }
        /*
         * id等于updateStu.id,则返回0;
         * id大于updateStu.id,则返回1;
         * id小于updateStu.id,则返回-1;
        */
        @Override
        public int compareTo(Object o) {
            UpdateStu updateStu = (UpdateStu)o;
            int result = (id > updateStu.id)? 1:(id == updateStu.id? 0:-1);
            return result;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public static void main(String[] args) {
            UpdateStu stu1 = new UpdateStu("李同学", 1001);
            UpdateStu stu2 = new UpdateStu("陈同学", 1002);
            UpdateStu stu3 = new UpdateStu("王同学", 1003);
            UpdateStu stu4 = new UpdateStu("马同学", 1004);
    
            TreeSet <UpdateStu> treeSet = new TreeSet<>();  //实例化TreeSet集合
            treeSet.add(stu1);   //向集合添加对象
            treeSet.add(stu2);
            treeSet.add(stu3);
            treeSet.add(stu4);
    
            Iterator<UpdateStu> iterator = treeSet.iterator();   //创建Set集合的迭代器
            System.out.println("Set集合中的所有元素:");
            while (iterator.hasNext()){            //遍历集合
                UpdateStu upd = (UpdateStu)iterator.next();
                System.out.println(upd.getId() + " " + upd.getName());
            }
    
            Iterator<UpdateStu> iterator2 = treeSet.headSet(stu2).iterator();   //截取stu2之前的元素,不包括stu2
            System.out.println("截取前面部分的集合:");
            while (iterator2.hasNext()){           //遍历集合
                UpdateStu upd = (UpdateStu)iterator2.next();
                System.out.println(upd.getId() + " " + upd.getName());
            }
    
            Iterator<UpdateStu> iterator3 = treeSet.subSet(stu2, stu3).iterator();   //截取stu2~stu3之间的元素,不包括stu3
            System.out.println("截取中间部分的集合:");
            while (iterator3.hasNext()){           //遍历集合
                UpdateStu upd = (UpdateStu)iterator3.next();
                System.out.println(upd.getId() + " " + upd.getName());
            }
        }
    }
    
    运行结果:
    Set集合中的所有元素:
    1001 李同学
    1002 陈同学
    1003 王同学
    1004 马同学
    截取前面部分的集合:
    1001 李同学
    截取中间部分的集合:
    1002 陈同学
    

    在上述代码中,存入TreeSet类实现的Set集合必须实现Comparable接口,该接口中的compaareTo(Object o)方法比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、0或正整数。

    技巧:headSet()、subSet()、tailSet()方法截取对象生成新集合时是否包含指定的参数,可以通过如下方法判断:如果指定参数位于新集合的起始位置,则包含该对象;如果指定参数是新集合的终止位置,则不包含该对象。

    五、Map集合

    • Map集合没有继承Collection接口,其提供的是key到value的映射
    • Map中不能包含相同的key,每个key只能映射一个value。
    • key还决定了存储对象在映射中的位置,但不是由key对象本身决定的,而是通过一种“散列技术”进行处理,产生一个散列码的整数值。
    • Map集合包括Map接口以及Map接口的所有实现类。

    1、Map接口

    Map接口提供了将key映射到值得对象。Map接口中常见得接口如下所示:

    方法 功能描述
    put (K key, V value) 向集合中添加指定的key和value的映射关系
    containsKey (Object key) 如果此映射包含key的映射关系,则返回true
    containsValue (Object Value) 如果此映射将一个或多个key映射到此值,则返回true
    get (Object key) 如果存在指定的key对象,则返回该对象对应的值,否则返回null
    keySet() 返回该集合中所有的key对象形成的Set集合
    values() 返回该集合中所有的值对象形成的Collection集合
    import java.util.*;
    
    public class MapInterface {
        public static void main(String[] args) {
    
            Map<String, String> map = new HashMap<>();    //创建HashMap集合对象
            map.put("1001","李若彤");     //向集合中添加对象
            map.put("1002","古天乐");
            map.put("1003","周星驰");
    
            Set <String> set = map.keySet();   //构建Map集合中所有key对象的集合
            Iterator iterator = set.iterator();
            System.out.println("key集合中的元素:");
            while (iterator.hasNext()){      //遍历集合
                System.out.println(iterator.next());
            }
    
            Collection <String> collection = map.values();   //构建Map集合中所有value对象的集合
            iterator = collection.iterator();
            System.out.println("value集合中的元素:");
            while (iterator.hasNext()){      //遍历集合
                System.out.println(iterator.next());
            }
        }
    }
    
    运行结果:
    key集合中的元素:
    1003
    1002
    1001
    value集合中的元素:
    周星驰
    古天乐
    李若彤
    

    说明:Map集合中允许value对象是null,而且没有个数限制。例如,可以通过“map.put("1001", null);”语句向集合中添加对象。

    3、Map接口的实现类

    Map接口常用的实现类有HashMap和TreeMap类;

    • 建议使用HashMap类实现Map集合,因为由HashMap类实现的Map集合添加删除映射关系效率更高
    • HashMap是基于哈希表的Map接口实现的,HashMap通过哈希码对内部的映射关系进行快速查找。
    • TreeMap中的映射关系存在一定的顺序,如果希望Map集合中的对象存在一定的顺序,应该使用TreeMap类实现Map集合。
    1. HashMap类的特点
    • 基于哈希表的Map接口实现,提供所有可选的映射操作,并允许使用null值和null健,但必须保证健的唯一性。
    • HashMap通过哈希表对其内部的映射关系进行快速查找。
    • HashMap类不保证映射的顺序,特别是它不保证该顺序恒久不变。
    1. TreeMap类的特点
    • TreeMap类不仅实现了Map接口,还实现了java.util.SortedMap接口,因此,集合中的映射关系具有一定的顺序。
    • 在添加、删除和定位映射关系时,TreeMap类比HashMap类性能稍差。
    • 由于TreeMap类实现的Map集合中的映射关系是根据健对象按照一定的顺序排列的,因此不允许对象健对象(key)是null。

    可以通过HashMap类创建Map集合,当需要顺序输出时,再创建一个完成相同映射关系的TreeMap类实例。

    import java.util.*;
    
    class Emp{
        private String e_id;
        private String e_name;
    
        public Emp(String e_id, String e_name) {
            this.e_id = e_id;
            this.e_name = e_name;
        }
    
        public String getE_id() {
            return e_id;
        }
    
        public void setE_id(String e_id) {
            this.e_id = e_id;
        }
    
        public String getE_name() {
            return e_name;
        }
    
        public void setE_name(String e_name) {
            this.e_name = e_name;
        }
    }
    
    public class MapTest {
        public static void main(String[] args) {
            Map <String,String> map = new HashMap<>();      //HashMap实现的Map对象
    
            Emp emp1 = new Emp("123","张三");    //创建对象
            Emp emp2 = new Emp("102","李四");
            Emp emp3 = new Emp("145","王五");
            Emp emp4 = new Emp("110","赵六");
    
            map.put(emp1.getE_id(),emp1.getE_name());      //将对象添加至Map集合中
            map.put(emp2.getE_id(),emp2.getE_name());
            map.put(emp3.getE_id(),emp3.getE_name());
            map.put(emp4.getE_id(),emp4.getE_name());
    
            Set <String> set = map.keySet();      //获取Map集合中的key对象的集合
            Iterator <String> iterator = set.iterator();
            System.out.println("HashMap实现的Map集合,无序:");
            while (iterator.hasNext()){           //遍历集合
                String str = (String)iterator.next();   //获取Map集合中的所有key值
                String name = map.get(str);             //获取Map集合中的所有value值
                System.out.println(str + " " + name);
            }
    
            TreeMap <String,String> treeMap = new TreeMap<>();    //创建TreeMap集合对象
            treeMap.putAll(map);     //向TreeMap集合对象中添加Map集合对象,使之具备相同的映射关系
            Iterator iterator1 = treeMap.keySet().iterator();
            System.out.println("TreeMap实现的Map集合,Key对象升序:");
            while (iterator1.hasNext()){      //遍历集合
                String str = (String) iterator1.next();    //获取Map集合中的所有key值
                String name = treeMap.get(str);            //获取Map集合中的所有value值
                System.out.println(str + " " + name);
            }
         }
    }
    
    运行结果:
    HashMap实现的Map集合,无序:
    110 赵六
    123 张三
    145 王五
    102 李四
    TreeMap实现的Map集合,Key对象升序:
    102 李四
    110 赵六
    123 张三
    145 王五
    
  • 相关阅读:
    命名mangling(压榨)
    Redis的源代码分析
    开源数据库 Sharding 技术 (Share Nothing)
    Python中time模块详解
    关于海量数据的数据模型
    字符数组,字符指针,Sizeof总结
    ConfigParser模块的使用
    分享懒人张RDLC报表(七、八)
    VS中提示:未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值。
    VS用正则表达式统计代码行数
  • 原文地址:https://www.cnblogs.com/xuliang-daydayup/p/12917008.html
Copyright © 2020-2023  润新知