Java 中的 List、Set、Map

集合 Collection 和 List、Set、Map 之间的关系如下图所示:

集合

其中,ArrayList、HashSet 和 HashMap 为常用类。

集合相比数组的优势:
1. 数组长度固定,而集合长度可变。
2. 数组只能通过下标访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象。

1. List

List 是元素 有序可重复 的集合,称为 序列

List 可以精确控制每个元素的插入位置,或删除某个位置的元素。
ArrayList:数组序列,List 接口的一个重要实现类,ArrayList 底层是由数组来实现的。

下面以学生课程管理为例,介绍 List 的用法。

首先新建一个课程类,包含课程编号和课程名,代码如下:

public class Course {

    private String id;
    private String name;

    public Course(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }   
}

1.1 向 List 中添加元素

创建一个类,名为 ListTest,用 add() 方法添加一个项目。
示例代码:

public class ListTest {

    // 用于存放待选课程的 List
    public List<Course> coursesForSelect;

    public ListTest() {
        this.coursesForSelect = new ArrayList<Course>();// 注意 List 是接口,不能实例化
    }

    // 测试 add 方法
    public void testAdd() {
        // add方法一
        Course c1 = new Course("1", "数据结构");
        coursesForSelect.add(c1);// 添加到第0个位置,若再用此方法,则依次向后排列

        // add方法二(添加到指定位置)
        Course c2 = new Course("2", "C语言");
        coursesForSelect.add(0, c2);// 添加到第0个位置,把原先第0个位置的挤到第1个

        // 注意:若添加位置大于 List 长度,则会抛出异常 IndexOutOfBoundsException
    //  Course c3 = new Course("3", "test");
    //  coursesForSelect.add(3, c3);
    }
}

添加多个项目,addAll() 方法。
示例代码:

public void testAdd() {
    // addAll方法一
    Course[] c4 = {new Course("3", "汇编语言"), new Course("4","Java")};
    coursesForSelect.addAll(Arrays.asList(c4));

    // addAll方法二,添加到指定位置
    Course[] c5 = {new Course("5", "高等数学"), new Course("6","概率论")};
    coursesForSelect.addAll(2, Arrays.asList(c5));

    // 下面几句仅供测试添加效果
    Course t5 = coursesForSelect.get(2);
    Course t6 = coursesForSelect.get(3);
    System.out.println("添加了课程:" + t5.getId() + "." + t5.getName());
    System.out.println("添加了课程:" + t6.getId() + "." + t6.getName());
}

1.2 获取 List 的元素

获取 List 中的元素,有三种方法。

1、用 get() 方法,示例代码:

public void testGet() {
    int size = coursesForSelect.size();// 获取数组长度
    System.out.println("有以下待选课程:");
    for (int i=0; i<size; i++) {
        Course c = coursesForSelect.get(i);
        System.out.println("课程:" + c.getId() + "." + c.getName());
    }
}

2、 用迭代器 Iterator,示例代码:

public void testIterator() {
    Iterator<Course> it = coursesForSelect.iterator();
    System.out.println("有以下待选课程:");
    while(it.hasNext()) {
        Course c = it.next();
        System.out.println("课程:" + c.getId() + "." + c.getName());
    }
}

3、 foreach 方法(即增强的 for 循环),示例代码:

public void testForeach() {
    System.out.println("有以下待选课程:");
    for(Course c : coursesForSelect) {
        System.out.println("课程:" + c.getId() + "." + c.getName());
    }
}

1.3 修改 List 的元素

set() 方法,示例代码:

public void testModify() {
    coursesForSelect.set(2, new Course("7","大学历史"));
}

1.4 删除 List 的元素

删除 List 中的元素有两种方法:remove() 和 removeAll()。
PS: 类似 add 和 addAll 方法。

删除某个元素:remove方法

public void testRemove() {
    // 删除某个元素:remove方法
    Course c = coursesForSelect.get(3);
    coursesForSelect.remove(c);// 删除第三个元素
    testForeach();// 显示所有课程(测试删除后的效果)
}

删除多个元素:removeAll方法

public void testRemove() {
    Course[] cc = {coursesForSelect.get(0), coursesForSelect.get(1)};
    coursesForSelect.removeAll(Arrays.asList(cc));// 删除第0和第1个元素
    testForeach();// 显示所有课程(测试删除后的效果)
}

2. Set

Set 是元素 无序不重复 的集合,称为
HashSet:哈希集,Set接口 的一个重要实现类。

小例子
功能:运行该程序后,控制台显示课程 ID 及课程名字,提示输入课程 ID 来选课。

创建一个学生类,

public class Student {

    private String id;
    private String name;

    public Set<Course> courses;

    public Student(String id, String name) {
        this.id = id;
        this.name = name;
        this.courses = new HashSet<Course>();// 这里是 HashSet
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

创建一个 SetTest 类(add 方法同 ListTest),

public class SetTest {

    public List<Course> coursesForSelect;

    public SetTest() {
        this.coursesForSelect = new ArrayList<Course>();
    }

    public void testAdd() {
        // add方法一
        Course c1 = new Course("1", "数据结构");
        coursesForSelect.add(c1);

        // add方法二(添加到指定位置)
        Course c2 = new Course("2", "C语言");
        coursesForSelect.add(0, c2);// 添加到第0个位置,把原先第0个位置的挤到第1个

        // addAll方法一(添加多个项目)
        Course[] c4 = {new Course("3", "汇编语言"), new Course("4","Java")};
        coursesForSelect.addAll(Arrays.asList(c4));

        // addAll方法二,添加(多个项目)到指定位置
        Course[] c5 = {new Course("5", "高等数学"), new Course("6","概率论")};
        coursesForSelect.addAll(2, Arrays.asList(c5));
    }

    /**
     * 通过for each(即增强for循环)访问集合元素
     */
    public void testForeach() {
        System.out.println("有以下待选课程:");
        for(Course c : coursesForSelect) {
            System.out.println("课程:" + c.getId() + "." + c.getName());
        }
    }

    public void p(Student st) {
        // 循环遍历输出学生所选课程
        for (Course c : st.courses) {
            System.out.println("选择了课程:" + c.getId() + "." + c.getName());
        }
    }

    public static void main(String[] args) {
        SetTest st = new SetTest();
        st.testAdd();
        st.testForeach();

        // 创建一个学生对象
        Student s = new Student("1", "小明");
        System.out.println("欢迎" + s.getName() + "选课!");

        // 创建一个Scanner对象,用来接收从键盘输入的课程ID
        Scanner console = new Scanner(System.in);

        for (int i=0; i<3; i++) {
            System.out.println("请输入课程ID:");
            String courseId = console.next();
            for (Course c : st.coursesForSelect) {
                if (c.getId().equals(courseId)) {
                    s.courses.add(c);
                    //s.courses.add(null);// OK,但无实际意义
                    //s.courses.add(c);// Set中的元素是不重复的,即使多次添加最后也只保留一个该对象的引用,因此加不加本句无影响
                }
            }
        }

        st.p(s);
        System.out.println();   
    }
}

该程序运行后,控制台输出:
1

输入1,2,3(序号可在给定范围自由选择,此处仅示例) 后控制台输出:
2

Set 是无序的,因而每次输出顺序可能和输入有不同。
Q: 为嘛我实验的总是相同??

注意:由于 Set 无序,因此循环遍历 Set 中的元素只能用 foreach 方法或 Iterator 方法,而不能使用 get 方法。

3. Map

Map 接口提供了一种映射关系,其中的关系是以 键-值对 (key-value)的形式存储的,能够根据 key 快速查找 value。

Map 中的键值对以 Entry 类型的对象实例形式存在,如图所示:

Entry

Map 中的 key 不能重复,value 可重复。

3.1 向 Map 添加映射

添加元素: put 方法。

小例子:
新建 MapTest 类,添加学生ID,判断是否被占用,若未被占用,则输入姓名,创建新学生对象,并且添加到students中

public class MapTest {

    /**
     * 装学生对象
     */
    public Map<String, Student>students;

    /**
     * 构造方法中初始化students
     */
    public MapTest() {
        this.students = new HashMap<String, Student>();
    }

    public void testPut() {
        // 创建一个Scanner对象,获取键盘输入的学生ID和姓名
        Scanner console = new Scanner(System.in);
        int i=0;
        while(i<3) {
            System.out.println("请输入学生ID:");
            String id = console.next();
            // 判断ID是否被占用
            Student s = students.get(id);
            if (s == null) {
                // 提示输入学生姓名
                System.out.println("请输入学生姓名:");
                String name = console.next();

                Student newS = new Student(id, name);           
                students.put(id, newS);// 通过调用 students 的 put 方法添加 ID-Student 映射
                System.out.println("成功添加学生:" + newS.getId() + "." + newS.getName());
                    i ++;
            } else {
                System.out.println("该学生ID已被占用!");
                continue;// 让循环继续
            }
        }
    }
}

3.2 删除 Map 中的映射

使用 remove 方法(只删除 key 即可),

public void testRemove() {
    // 提示要删除的学生ID
    System.out.println("请输入要删除的学生ID:");

    // 获取从键盘输入的待删除的学生ID字符串
    Scanner console = new Scanner(System.in);
    while(true) {
        String id = console.next();

        // 判断该ID是否有对应的学生对象
        Student s = students.get(id);
        if (s == null) {
            System.out.println("该ID不存在!");
            continue;// 让循环继续进行
        }
        students.remove(id);
        System.out.println("成功删除学生:" + s.getName());
            break;// 退出循环
        }
    }

3.3 修改 Map 中的映射

也用 put 方法实现,

public void testModify() {
    // 提示要修改的学生ID
    System.out.println("请输入要修改的学生ID:");

    // 创建一个Scanner对象,去获取键盘上输入的学生ID字符串
    Scanner console = new Scanner(System.in);

    while(true) {
        // 取得从键盘输入的学生ID
        String sID = console.next();

        // 从students中查找该学生ID对应的学生对象
        Student s = students.get(sID);
        if (s == null) {
            System.out.println("该ID不存在,请重新输入!");
            continue;
        }

        // 提示当前对应的学生对象的姓名
        System.out.println("当前该学生ID,所对应的学生为:" + s.getName());

        // 提示输入新的学生姓名,修改
        System.out.println("请输入新的学生姓名:");
        String name = console.next();
        Student newS = new Student(sID, name);
        students.put(sID, newS);
        System.out.println("修改成功!");
        break;
    }
}

3.4 遍历 Map 中的元素

3.4.1 keySet 方法

keySet 方法,返回 Map 中所有 的集合。

public void testKeySet() {
    // 通过keySet方法,返回 Map 中的所有‘键’的Set集合
    Set<String> keySet = students.keySet();

    // 取得students的容量
    System.out.println("总共有 " + students.size() + " 个学生!");

    // 遍历 keySet,取得每一个键,再调用get方法取得每个键对应的value
    for (String sId : keySet) {
        Student s = students.get(sId);
        if(s != null) {
            System.out.println("学生:" + s.getName());
        }
    }
}

3.4.2 entrySet 方法

entrySet 方法:返回 键-值对 的集合。

public void testEntrySet() {
    // 通过entrySet方法,返回Map中所有键值对
    Set<Entry<String,Student>> entrySet = students.entrySet();// 注意:Entry也是有泛型的<String,Student>
    for (Entry<String, Student> entry : entrySet) {
        System.out.println("取得键:" + entry.getKey());
        System.out.println("取得值:" + entry.getValue().getName());// getValue返回值类型和泛型value类型一致,因此可直接调用getName
    }
} 

3.4.3 values 方法

values 方法:返回 的集合。
示例代码:

Collection c = map.values();  
Iterator iterator = c.iterator();  
while(iterator.hasNext()) {  
      System.out.println("value:"+ iterator.next());   
}

PS: 主要内容整理总结自 慕课网

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值