Java 集合框架

来源:互联网 发布:微信斗图软件 编辑:程序博客网 时间:2024/06/04 00:22

Java 集合框架

知识点

Collection 接口Map 接口List 和 ArrayListSet 和 HashSetHashMap

集合框架的介绍

我们在超市买东西的时候,如果没有购物车是不是会很麻烦呢?Java 中集合类是一种工具类,就是像购物车一样的容器,存储任意数量的具有共同属性的对象。

我们为什么要用集合呢?一个类的内部有许多相同类型的属性,并且他们的作用与意义是一样的,我们最好用一个类似容器的东西去盛放他们,在类的内部就变得井然有序。所以集合便是在类的内部,对数据进行组织的作用。这样我们便可以简单而快速地搜索大量的条目。有的集合接口,提供了一系列排列有序的元素,并且可以在序列中快速地插入或者删除有关元素。还有一些集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型。

集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大内容:对外的接口、接口的实现和对集合运算的算法。

下图是简化的集合框架关系图:
这里写图片描述


接口

Collection 接口

因为集合框架中的很多类功能是相似的,所以我们用接口来规范类。Collection 接口是 java 集合框架里的一个根接口。它也是 List、Set 和 Queue 接口的父接口。Collection 接口中定义了可用于操作 List、Set 和 Queue 的方法——增删改查。

方法  返回值     说明add(E e)    boolean     向 collection 的尾部追加指定的元素(可选操作)addAll(Collection<? extend E> c)    boolean     将指定 collection 中的所有元素都添加到此 collection 中(可选操作)clear()     void    移除此 collection 中的所有元素(可选操作)contains(Object o)  boolean     如果此 collection 包含指定的元素,则返回 truecontainsAll(Collection<?> c)    boolean     如果此 collection 包含指定 collection 的所有元素,则返回 trueequals(Object o)    boolean     比较此 collection 与指定对象是否相等hashCode()  int     返回此 collection 的哈希码值isEmpty()   boolean     如果此 collection 不包含元素,则返回trueiterator()  Iterator    返回在此 collection 的元素上进行迭代的迭代器remove(Object o)    boolean     移除此 collection 中出现的首个指定元素(可选操作)removeAll(Collection<?> c)  boolean     移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)retainAll(Collection<?> c)  boolean     仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)size()  int     返回此 collection 中的元素数toArray()   Object[]    返回包含此 collection 中所有元素的数组toArray(T[] a)  T[]     返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同

Map 接口

Map 接口也是一个非常重要的集合接口,用于存储键/值对。Map 中的元素都是成对出现的,键值对就像数组的索引与数组的内容的关系一样,将一个键映射到一个值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。我们可以通过键去找到相应的值。

这里写图片描述

value 可以存储任意类型的对象,我们可以根据 key 键快速查找 value。Map 中的键/值对以 Entry 类型的对象实例形式存在。

看一看 Map 中的方法吧

方法  返回值     说明clear()     void    从此映射中移除所用映射关系(可选操作)containsKey(Object key)     boolean     如果此映射包含指定键的映射关系,则返回truecontainsValue(Object value)     boolean     如果此映射将一个或多个键映射到指定值,则返回 trueentrySet()  Set>    返回此映射中包含的映射关系的 Set 视图equals(Object o)    boolean     比较指定的对象与此映射是否相等get(Object key)     V   返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 nullhashCode()  int     返回此映射的哈希码值isEmpty()   boolean     如果此映射未包含键-值映射关系,则返回 truekeySet()    Set     返回此映射中包含的键的 Set 视图put(K key, V value)     V   将指定的值与此映射中的指定键关联(可选操作)putAll(Map<? extends K, ? extends V> m)     void    从指定映射中将所有映射关系复制到此映射中(可选操作)remove(Object key)  V   如果存在一个键的映射关系,则将其从此映射中移除(可选操作)size    int     返回此映射中的键-值映射关系数values()    Collection  返回此映射中包含的值的 Collection 视图

具体类

List 接口与 ArrayList 类

List 是一个接口,不能实例化,需要一个具体类来实现实例化。List 集合中的对象按照一定的顺序排放,里面的内容可以重复。 List 接口实现的类有:ArrayList(实现动态数组),Vector(实现动态数组),LinkedList(实现链表),Stack(实现堆栈)。

List 在 Collection 基础上增加的方法:

方法  返回值     说明add(int index, E element)   void    在列表的指定位置插入指定元素(可选操作)addAll(int index, Collection<? extends E> c)    boolean     将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)get(int index)  E   返回列表中指定位置的元素indexOf(Object o)   int     返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1lastIndexOf(Object o)   int     返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1listIterator()  ListIterator    返回此列表元素的列表迭代器(按适当顺序)listIterator(int index)     ListIterator    返回此列表元素的列表迭代器(按适当顺序),从列表的指定位置开始remove(int index)   E   移除列表中指定位置的元素(可选操作)set(int index, E element)   E   用指定元素替换列表中指定位置的元素(可选操作)subList(int fromIndex, int toIndex)     List    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图

学习 java.util.ArrayList,ArrayList 类实现一个可增长的动态数组,它可以存储不同类型的对象,而数组则只能存放特定数据类型的值。

实际的例子来学习ArrayList吧!学校的教务系统会对学生进行统一的管理,每一个学生都会有一个学号和学生姓名,我们在维护整个系统的时候,大多数操作是对学生的添加、插入、删除、修改等操作。

先创建一个学生类:

package com.shiyanlou.test_collection_demo;/* * 学生类 */public class Student {    public String id;    public String name;    public Student(String id, String name){        this.id = id;        this.name = name;    }}

创建一个学生列表,来管理学生

package com.shiyanlou.test_collection_demo;import java.util.ArrayList;import java.util.Arrays;import java.util.Iterator;import java.util.List;public class ListTest {    /*     * 用于存放学生的List     */    //集合后面的<>代表泛型的意思    //泛型是规定了集合元素的类型    //我们以后会详细讲到    public List<Student> students;    public ListTest() {        this.students = new ArrayList<Student>();    }    /*     * 用于往students中添加学生     */    public void testAdd() {        // 创建一个学生对象,并通过调用add方法,添加到学生管理List中        Student st1 = new Student("1", "张三");        students.add(st1);        // 取出 List中的Student对象        Student temp = students.get(0);        System.out.println("添加了学生:" + temp.id + ":" + temp.name);        Student st2 = new Student("2", "李四");        students.add(0, st2);        Student temp2 = students.get(0);        System.out.println("添加了学生:" + temp2.id + ":" + temp2.name);        // 对象数组的形式添加        Student[] student = { new Student("3", "王五"), new Student("4", "马六") };        // Arrays类包含用来操作数组(比如排序和搜索)的各种方法,asList() 方法用来返回一个受指定数组支持的固定大小的列表        students.addAll(Arrays.asList(student));        Student temp3 = students.get(2);        Student temp4 = students.get(3);        System.out.println("添加了学生:" + temp3.id + ":" + temp3.name);        System.out.println("添加了学生:" + temp4.id + ":" + temp4.name);        Student[] student2 = { new Student("5", "周七"), new Student("6", "赵八") };        students.addAll(2, Arrays.asList(student2));        Student temp5 = students.get(2);        Student temp6 = students.get(3);        System.out.println("添加了学生:" + temp5.id + ":" + temp5.name);        System.out.println("添加了学生:" + temp6.id + ":" + temp6.name);    }    /*     * 取得List中的元素的方法     */    public void testGet() {        int size = students.size();        for (int i = 0; i < size; i++) {            Student st = students.get(i);            System.out.println("学生:" + st.id + ":" + st.name);        }    }    /*     * 通过迭代器来遍历     */    // 迭代器的工作是遍历并选择序列中的对象,Java 中 Iterator 只能单向移动    public void testIterator() {        // 通过集合的iterator方法,取得迭代器实例        Iterator<Student> it = students.iterator();        System.out.println("有如下学生(通过迭代器访问):");        while (it.hasNext()) {            Student st = it.next();            System.out.println("学生" + st.id + ":" + st.name);        }    }    /**     * 通过for each 方法访问集合元素     *      * @param args     */    public void testForEach() {        System.out.println("有如下学生(通过for each):");        for (Student obj : students) {            Student st = obj;            System.out.println("学生:" + st.id + ":" + st.name);        }    }    /**     * 修改List中的元素     *      * @param args     */    public void testModify() {        students.set(4, new Student("3", "吴酒"));    }    /**     * 删除List中的元素     *      * @param args     */    public void testRemove() {        Student st = students.get(4);        System.out.println("我是学生:" + st.id + ":" + st.name + ",我即将被删除");        students.remove(st);        System.out.println("成功删除学生!");        testForEach();    }    public static void main(String[] args) {        ListTest lt = new ListTest();        lt.testAdd();        lt.testGet();        lt.testIterator();        lt.testModify();        lt.testForEach();        lt.testRemove();    }}

Arrays 包含用来操作数组(比如排序和搜索)的各种方法,asList() 方法用来返回一个受指定数组支持的固定大小的列表。

List 有两种基本的类型,除了 ArrayList 外,还有 LinkedList,LinkedList 类用于创建链表数据结构,两者的对比如下:

ArrayList:它擅长于随机访问元素,但是插入和移除元素时较慢。LinkedList:它通过代价较低的在 List 中进行插入和删除操作,提供了优化的顺序访问,它在随机访问方面相对较慢,但是它的特性集较 ArrayList 更大。

Set 接口和 HashSet 类

Set接口也是 Collection 接口的子接口,它有一个很重要也是很常用的实现类——HashSet,Set 是元素无序并且不包含重复元素的 collection(List 可以重复),被称为集。

HashSet 由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。

接下来我们同样通过代码的形式来详细看一看吧!

在上面我们实现了学生的管理,现在学生要做项目,每个项目有一个组长,由组长来组织组员,我们便来实现项目组的管理吧。(接上面的程序实例)

因为项目组的组长由一个老师担任,首先我们来创建一个 PD 类

package com.shiyanlou.test_collection_demo;import java.util.HashSet;import java.util.Set;/* * 项目组长类 */public class PD {    public String id;    public String name;    //集合后面的<>代表泛型的意思    //泛型是规定了集合元素的类型    //我们以后会详细讲到    public Set<Student> students;    public PD(String id, String name){        this.id = id;        this.name = name;        this.students = new HashSet<Student>();    }}

创建一个SetTest 类,用来管理项目成员

package com.shiyanlou.test_collection_demo;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Scanner;public class SetTest {    public List<Student> students;    public SetTest() {        students = new ArrayList<Student>();    }    /*     * 用于往students中添加学生     */    public void testAdd() {        //创建一个学生对象,并通过调用add方法,添加到学生管理List中        Student st1 = new Student("1", "张三");        students.add(st1);        //添加到List中的类型均为Object,所以取出时还需要强转        Student st2 = new Student("2","李四");        students.add(st2);        Student[] student = {new Student("3", "王五"),new Student("4", "马六")};        students.addAll(Arrays.asList(student));        Student[] student2 = {new Student("5", "周七"),new Student("6", "赵八")};        students.addAll(Arrays.asList(student2));    }    /**     * 通过for each 方法访问集合元素     * @param args     */    public void testForEach() {        System.out.println("有如下学生(通过for each):");        for(Object obj:students){            Student st = (Student)obj;            System.out.println("学生:" + st.id + ":" + st.name);        }    }    public static void main(String[] args){        SetTest st = new SetTest();        st.testAdd();        st.testForEach();        PD pd = new PD("1","张老师");        System.out.println("请:" + pd.name + "选择小组成员!");        //创建一个 Scanner 对象,用来接收从键盘输入的学生 ID        Scanner console = new Scanner(System.in);        for(int i = 0;i < 3; i++){            System.out.println("请输入学生 ID");            String studentID = console.next();            for(Student s:st.students){                if(s.id.equals(studentID)){                    pd.students.add(s);                }            }        }        st.testForEachForSer(pd);        // 关闭 Scanner 对象        console.close();    }    //打印输出,老师所选的学生!Set里遍历元素只能用foreach 和 iterator     //不能使用 get() 方法,因为它是无序的,不能想 List 一样查询具体索引的元素    public void testForEachForSer(PD pd){        for(Student s: pd.students) {        System.out.println("选择了学生:" + s.id + ":" + s.name);        }    }}

HashMap 类

HashMap 是基于哈希表的 Map 接口的一个重要实现类。HashMap 中的 Entry 对象是无序排列的,Key 值和 value 值都可以为 null,但是一个 HashMap 只能有一个 key 值为 null 的映射(key 值不可重复)。

创建一个 Course 类:

package com.shiyanlou.test_collection_demo;public class Course {    public String id;    public String name;    public Course(String id, String name){        this.id = id;        this.name = name;    }}

创建一个 MapTest 类:

package com.shiyanlou.test_collection_demo;import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;import java.util.Scanner;import java.util.Set;public class MapTest {    /**     * 用来承装课程类型对象     */    public Map<String, Course> courses;    /**     * 在构造器中初始化 courses 属性     * @param args     */    public MapTest() {        this.courses = new HashMap<String, Course>();    }    /**     * 测试添加:输入课程 ID,判断是否被占用     * 若未被占用,输入课程名称,创建新课程对象     * 并且添加到 courses 中     * @param args     */    public void testPut() {        //创建一个 Scanner 对象,用来获取输入的课程 ID 和名称        Scanner console = new Scanner(System.in);        for(int i = 0; i < 3; i++) {            System.out.println("请输入课程 ID:");            String ID = console.next();            //判断该 ID 是否被占用            Course cr = courses.get(ID);            if(cr == null){                //提示输入课程名称                System.out.println("请输入课程名称:");                String name = console.next();                //创建新的课程对象                Course newCourse = new Course(ID,name);                //通过调用 courses 的 put 方法,添加 ID-课程映射                courses.put(ID, newCourse);                System.out.println("成功添加课程:" + courses.get(ID).name);            }            else {                System.out.println("该课程 ID 已被占用");                continue;            }        }    }    /**     * 测试 Map 的 keySet 方法     * @param args     */    public void testKeySet() {        //通过 keySet 方法,返回 Map 中的所有键的 Set 集合        Set<String> keySet = courses.keySet();        //遍历 keySet,取得每一个键,在调用 get 方法取得每个键对应的 value        for(String crID: keySet) {            Course cr = courses.get(crID);            if(cr != null){                System.out.println("课程:" + cr.name);            }        }    }    /**     * 测试删除 Map 中的映射     * @param args     */    public void testRemove() {        //获取从键盘输入的待删除课程 ID 字符串        Scanner console = new Scanner(System.in);        while(true){            //提示输出待删除的课程 ID            System.out.println("请输入要删除的课程 ID!");            String ID = console.next();            //判断该 ID 是否对应的课程对象            Course cr = courses.get(ID);            if(cr == null) {                //提示输入的 ID 并不存在                System.out.println("该 ID 不存在!");                continue;            }            courses.remove(ID);            System.out.println("成功删除课程" + cr.name);            break;        }    }    /**     * 通过 entrySet 方法来遍历 Map     * @param args     */    public void testEntrySet() {        //通过 entrySet 方法,返回 Map 中的所有键值对        Set<Entry<String,Course>> entrySet = courses.entrySet();        for(Entry<String,Course> entry: entrySet) {            System.out.println("取得键:" + entry.getKey());            System.out.println("对应的值为:" + entry.getValue().name);        }    }    /**     * 利用 put 方法修改Map 中的已有映射     * @param args     */    public void testModify(){        //提示输入要修改的课程 ID        System.out.println("请输入要修改的课程 ID:");        //创建一个 Scanner 对象,去获取从键盘上输入的课程 ID 字符串        Scanner console = new Scanner(System.in);        while(true) {            //取得从键盘输入的课程 ID            String crID = console.next();            //从 courses 中查找该课程 ID 对应的对象            Course course = courses.get(crID);            if(course == null) {                System.out.println("该 ID 不存在!请重新输入!");                continue;            }            //提示当前对应的课程对象的名称            System.out.println("当前该课程 ID,所对应的课程为:" + course.name);            //提示输入新的课程名称,来修改已有的映射            System.out.println("请输入新的课程名称:");            String name = console.next();            Course newCourse = new Course(crID,name);            courses.put(crID, newCourse);            System.out.println("修改成功!");            break;        }    }    public static void main(String[] args) {        MapTest mt = new MapTest();        mt.testPut();        mt.testKeySet();        mt.testRemove();        mt.testModify();        mt.testEntrySet();    }}
原创粉丝点击