java 集合框架

java 集合框架

集合框架的介绍

我们在超市买东西的时候,如果没有购物车是不是会很麻烦呢?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包含指定元素,则返回true
containsAll(Collection<?> c) boolean 如果此collection包含指定collection的所有元素,则返回true
equals(Object o) boolean 比较此collection与指定对象是否相等
hashCode() int 返回此collection的哈希码值
isEmpty() boolean 如果此collection不包含元素 则返回true
iterator() Iterator<E> 返回在此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> T[] 返回包含此 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 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1
lastIndexOf(Object o) int 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1
listIterator() ListIterator<E> 返回此列表元素的列表迭代器(按适当顺序)
listIterator(int index) ListIterator<E> 返回此列表元素的列表迭代器(按适当顺序),从列表的指定位置开始
remove(int index) E 移除列表中指定位置的元素(可选操作)
set(int index, E element) E 用指定元素替换列表中指定位置的元素(可选操作)
subList(int fromIndex, int toIndex) List<E> 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图

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

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

先创建一个学生类:

/*
 * 学生类
 */

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

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

管理学生类:

import java.util.*;

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 方法访问集合元素
     *
     */
    public void testForEach() {
        System.out.println("有如下学生(通过 for each):");
        for (Student obj : students) {
            Student st = obj;
            System.out.println("学生:" + st.id + ":" + st.name);
        }
        //使用 java8 Steam 将学生排序后输出
        students.stream()//创建 Stream
                //通过学生 id 排序
                .sorted(Comparator.comparing(x -> x.id))
                //输出
                .forEach(System.out::println);
    }

    /**
     * 修改 List 中的元素
     *
     */
    public void testModify() {
        students.set(4, new Student("3", "吴酒"));
    }

    /**
     * 删除 List 中的元素
     *
     */
    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 类, Arrays 包含用来操作数组(比如排序和搜索)的各种方法,asList() 方法用来返回一个受指定数组支持的固定大小的列表。

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

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

Set接口 和 HashSet 类

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

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

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

在上面我们实现了学生的管理,现在学生要做项目,每一个项目有一个组长,由组长来组织组员,我们便来实现项目组的管理

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

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 类,用来管理项目成员

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 值不可重复)。

下面我们通过代码来学习 Map 中的方法吧。都有过选课经历吧,我们就用 Map 来管理课程吧

创建一个Course类

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

创建一个MapTest类:

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();

    }
}

参考链接

在线文档-jdk-zh

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容