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 王五
原文地址:https://www.cnblogs.com/xuliang-daydayup/p/12917008.html