浅入深出之Java集合框架(上)

Java中的集合框架(上)




由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架(下)>。

目录:

浅入深出之Java集合框架(上)

浅入深出之Java集合框架(中)   努力赶制中。。关注后更新会提醒哦!

浅入深出之Java集合框架(下) 努力赶制中。。关注后更新会提醒哦!


一、集合概述

1)集合的概念

现实生活中的集合:很多事物凑在一起。

数学中的集合:具有共同属性的事物的总体。

Java中的集合类:是一种工具类,就像是容器,储存任意数量的具有共同属性的对象。

2)集合的作用

如果一个类的内部有多相同类型的属性,并且它们的作用和意义是一样的。比如说,一个学生可以选多个课程,对于一个学生类来说,XX课程就是他的一个属性,而xx课程通常不只有一个。对于像这种情况,如果把每一个课程都定一个属性就太繁琐了,这里我们就要用到集合的概念。

    

综上所述,集合的作用有以下几点:

  1. 在类的内部,对数据进行组织。
  2. 简单而快速的搜索大数量的条目。
  3. 有的集合接口,提供了一系列排列有序的元素,并且可以在序列中间快速的插入或者删除有关元素。
  4. 有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型。

3)集合和数组的对比

可以看出集合和数组的功能类似,都是把一系列的数据放入到一个容器中,但是在类的内部我们为什么要用集合而不是数组呢?

  1. 数组的长度固定,集合长度可变。集合的优势就在于,集合的长度是随着里面的内容而扩充的,而数组的长度是已经定义好的。
  2. 数组只能通过下标访问元素,类型固定(数组下标只能是整形的),而有的集合可以通过任意类型查找所映射的具体对象(key关键字可以是任意类型)。

二、Java集合框架体系结构

我们来简单看一下java集合框架:(还有很多接口和类没有列出,这里只列出常用的接口和类)

如图所示,JAVA集合框架体系结构:Collection与Map是两个根接口。

Collection接口:内部存储的是一个个独立的对象。包含:

1、List接口:序列,存储元素排列有序且可重复。实现类:ArrayList,数组序列;实现类:LinkedList,链表。

2、Queue接口:队列,存储元素排列有序且可重复。实现类:LinkedList,链表。

3、Set接口:集,存储元素无序且不可重复。实现类:HashSet,哈希集。

Map接口:内部以<Key,Value>(任意类型)的一个映射去存储数据,这一个映射就是Entry类(Map的内部类)的实例。包括:实现类:HashMap,哈希表。

Collection接口是List、Set、Queue接口的父接口,Collection接口定义了可用于操作List、Set和Queue的方法--增删改查。(具体的Collection接口的方法可以通过查API,这里就不列举了。)

其中,ArrayList、HashSet和HashMap是使用最多的三个实现类,这里我们将逐个介绍这三个实现类。

在这篇文章中将先介绍ArrayList的用法。


三、ArrayList实现类

List接口及其实现类--ArrayList

List可以精确的控制每个元素的插入位置,或删除某个位置元素;

List有add()插入方法和get()获取方法;

ArrayList--数组序列,是List的一个重要实现类

ArrayList底层是由数组实现的,这也是其名字的由来。

那么如何使用这些集合呢?我们来通过一个小例子,写一个小程序来更直观的学习集合的使用方法。(之后的文章的例子也是基于此的)

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

程序功能——模拟学生选课功能

  1. 选择课程(往集合添加课程)
  2. 删除所选的某门课程(删除集合中的元素)
  3. 查看所选课程
  4. 修改所选课程

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

以下是该程序的代码片段,因为是用于测试来介绍集合的使用,所以请不要在意细节,代码会一步步改进的。

1)创建学生类和课程类

 1 /**
 2  * 学生类
 3  * @author hysum
 4  *
 5  */
 6 public class Student implements {
 7     private String name;//学生姓名
 8     private String id;//学生id
 9     private Set courses;//所选课程的set集合
10
11     public Student(){}
12     public Student(String id,String name){
13         this.id=id;
14         this.name=name;
15         this.courses=new HashSet();//初始化集合
16     }
17     public String getName() {
18         return name;
19     }
20     public void setName(String name) {
21         this.name = name;
22     }
23     public String getId() {
24         return id;
25     }
26     public void setId(String id) {
27         this.id = id;
28     }
29     public Set getCourses() {
30         return courses;
31     }
32     public void setCourses(Set courses) {
33         this.courses = courses;
34     }
 1 /**
 2  * 课程类
 3  * @author hysum
 4  *
 5  */
 6 public class Course {
 7 private String id;//课程id
 8     private String name;//课程名称
 9
10     public Course(){
11
12     }
13     public Course(String name){
14         this.name=name;
15     }
16     public String getId() {
17         return id;
18     }
19     public void setId(String id) {
20         this.id = id;
21     }
22     public String getName() {
23         return name;
24     }
25     public void setName(String name) {
26         this.name = name;
27     }
28     public Course(String id,String name){
29         this.id=id;
30         this.name=name;
31     }
32 }

2)创建备选课程类

 1 /**
 2  * 备选课程类
 3  *
 4  * @author hysum
 5  *
 6  */
 7 public class ListCourse {
 8 private List CoresesToSelect;// 备选课程
 9     private Student stu;
10     private static Scanner in;
11     {
12         in = new Scanner(System.in);
13     }
14     public ListCourse() {
15         this.CoresesToSelect = new ArrayList();// 初始化List集合
16     }
17        public List getCoresesToSelect() {
18         return CoresesToSelect;
19     }
20
21     public void setCoresesToSelect(List coresesToSelect) {
22         CoresesToSelect = coresesToSelect;
23     }   26 }

注意:

List是接口,所以在构造方法中不能直接实例化,而通过ArrayList()实例化!!!

例:public List coursesToSelect = new ArrayList();

Set、Map都类似,不可以直接对他实例化,要借助相应的实例化类如HashSet(),HashMap();

3)在备选课程里添加课程

(添加元素)List下总共有4个为List插入元素的方法 :

1.add(element);

2.add(index,element);

3.addAll(Arrays.asList(对象数组名));

4.addAll(index,Arrays.asList(对象数组名));

以下用代码示例:

 1 /*
 2  * 添加备选课程
 3  */
 4 public void AddCourse() {
 5         Course cr1=new Course("1","数据结构");//创建课程对象
 6     this.CoresesToSelect.add(cr1);//用add(element)添加
 7         Course temp=(Course)this.CoresesToSelect.get(0);//用get方法取出,注意类型转换
 8     System.out.println("添加了课程:"+temp.getId()+" "+temp.getName());
 9
10         Course cr2=new Course("2","C语言");//创建课程对象
11     this.CoresesToSelect.add(0,cr2);//用add(index,element)添加
12     temp=(Course)this.CoresesToSelect.get(0);
13         System.out.println("添加了课程:"+temp.getId()+" "+temp.getName());
14 }      
1 Course[] course = { new Course("1", "数据结构"), new Course("2", "C语言"), new Course("3", "汇编语言"),
2                 new Course("4", "离散数学") };
3         this.CoresesToSelect.addAll(Arrays.asList(course));//用addAll(Arrays.asList(对象数组名))添加

注意:

1.对象被存入集合都变成object类型了 取出时需要类型强转。(之后会用泛型来解决这个问题)

例:Course temp = (Course)coursesToSelect.get(0);

2.添加进list中的位置(index)介于[0,length]之间;0代表插到队头,length代表插到队尾。

3.如果添加到List中的长度大于他目前的长度,则系统会出现异常,即数组下表越界异常,如:

1 Course cr2=new Course("2","C语言");//创建课程对象
2 this.CoresesToSelect.add(2,cr2);//用add方法添加,超出集合现有长度 temp=(Course)

4)备选课程取出打印

以下三种方法都是用来取出List中元素的方法:

-----for循环-----

1 public void testGet(){
2 int size=CoursesToSelect.size();
3 for(int i=0;i<size;i++){
4 Course cr=(Course) CoursesToSelect.get(i);
5 System.out.println("取出的课程:"+cr.getId()+":"+cr.getName());
6 }
7 }

-----迭代器-----

Iterator是一个接口,依赖于集合存在的。

1 Iterator it=CourseToSelect.iterator();
2 while(it.hasNext()){
3 Course cr=(Course) it.next();
4 System.out.println("课程:" + cr.id + ":" + cr.name);
5 }

-----for each(推荐使用)-----

1 for(Object obj:CoursesToSelect){//遍历集合中的每一个元素,作为每一个Object变量
2 Course cr=(Course) obj;
3 System.out.println("课程:" + cr.id + ":" + cr.name);
4 }

5)备选课程修改

使用set(index,Object element)修改元素,index表示索引位置,element表示新对象。

1     /*
2      * 修改备选课程
3      */
4     public void Modify(int index, Course c) {// 传入要修改的参数
5         this.CoresesToSelect.set(index, c);
6     }

6)删除备选课程元素

List中有remove(index),remove(对象值)和removeAll(Arrays.asList(对象数组名))方法来删除容器中元素的值(用法和add类似)。

Course是信息课程类,有id和name属性;courseToSelect是list的序列容器对象。

 1     /*
 2      * 删除备选课程,跟添加方法类似
 3      */
 4     public void Remove(int index) {// 通过索引位置删除
 5         this.CoresesToSelect.remove(index);
 6     }
 7
 8     public void Remove(Course c) {// 通过课程对象删除
 9         this.CoresesToSelect.remove(c);
10
11     }
12
13     public void Remove(Course[] c) {// 通过集合对象删除
14         this.CoresesToSelect.removeAll(Arrays.asList(c));
15
16     }

注意:

1.remove(index);删除位置要大于0并且小于List(序列容器)的长度。如果要删除全部可以用for循环嵌套此方法。

2.remove(object);先要获得删除的值,用法是先定义一个信息变量通过get()来存放要删除的值,然后用remove(删除的对象值);

3.removeAll(Arrays.asList());要删除指定的多个位置  Arrays.asLIst(对象数组名);作用是把数组转换为集合。用法是先创建信息对象数组存放删除元素的值,然后再用removeAll(Arrays.asList(对象数组名))方法,删除集合数组的元素。


四、应用泛型管理课程

在上面的几个例子中,小伙伴是否发现对于集合的取出和遍历都要将Object对象进行强制转换后才能使用,每次这样做不仅增加了编程难度还使代码特别繁琐,这里我们可以利用泛型来帮助我们更加方便地使用java集合。

首先,我们要知道没有使用泛型的话,集合中的元素,可以是任意类型的对象(对象的引用),如果把某个对象放入集合,则会忽略他的类型把他当做Object处理。

那么我们就在刚才的例子里往备选课程类里的CoresesToSelect的List集合添加一些奇怪的东西会发什么有趣的事呢?

1    /*
2      * 往List中添加一些奇怪的东西
3      */
4      public void testType(){
5      System.out.println("能否往List中添加一些奇怪的东西呢?");
6      this.CoresesToSelect.add("我不是课程,我是字符串!");
7      }

当调用取出课程方法取出该元素时,运行时出错:

这是因为取出该元素时String类型不能强制转换为Course类型,那有什么办法来避免集合中被添加不希望添加的类型呢?

泛型则是规定了某个集合只可以存放特定类型的对象,会在编译期间进行类型检查,可以直接指定类型获取的集合元素。

泛型:指规定了某个集合只能存放特定类型的对象。

语法:ArrayList<String> array=new ArrayList<String>();  //规定array中只能存放String类型的对象

那么,了解了泛型之后,上面的例子里都可以加上泛型了,修改如下(只列出修改的部分):(自行对比)

1 private Set<Course> courses;//所选课程的set集合
2 this.courses=new HashSet<Course>();//初始化集合
3 public Set<Course> getCourses() {
4         return courses;
5     }
6     public void setCourses(Set<Course> courses) {
7         this.courses = courses;
8     }
 1 private List<Course> CoresesToSelect;// 备选课程
 2 public ListCourse() {
 3         this.CoresesToSelect = new ArrayList<Course>();// 初始化List集合
 4     }
 5 public List<Course> getCoresesToSelect() {
 6         return CoresesToSelect;
 7     }
 8
 9     public void setCoresesToSelect(List<Course> coresesToSelect) {
10         CoresesToSelect = coresesToSelect;
11     }

foreach循环的修改:

1 for (Course obj : CoresesToSelect) {
2     System.out.println("添加了课程:" + obj.getId() + " " + obj.getName());
4 }

运用了泛型的话,用foreach语句时 存储变量应该为泛型的类型。for(Course a:courseToSelect),不必再用Object取出再强转,因为已经规定容器里装的都是Course类型。

使用泛型要注意

1.泛型集合中,不能添加泛型规定的类型和其子类以外的对象,否则会报错!

2.泛型中可以添加规定的类型的子类型的对象。如:

1 public void testChild() {
2         ChildCourse ccr = new ChildCourse();
3         ccr.id = "3";
4         ccr.name = "我是子类型的课程对象实例~~";
5         courses.add(ccr);
6 }

3.不能直接添加基本类型(int,float等)的对象,如果要添加,需要使用其包装类。如:

1 public void testBasicType() {
2 List<Integer> list = new ArrayList<Integer>();
3 list.add(1);
4 System.out.println("基本类型必须使用包装类作为泛型!" + list.get(0));
5 }

五、通过Set集合管理课程

Set集合和List一样是Collection接口的子接口。它的方法跟List类似,但有稍许不同,因为Set集合是无序且不重复的。

1)添加学生选课的课程

add方法跟ArrayList一样

 1 li.stu=new Student("1","小明");
 2         System.out.println("欢迎"+li.stu.getName()+"同学选择课程");
 3         for(int i=0;i<3;i++){//循环三次添加选课
 4             System.out.println("请选第"+(i+1)+"门课程:");
 5             String Id=in.next();
 6             for(Course c:li.getCoresesToSelect()){
 7                 if(c.getId().equals(Id)){
 8                     li.stu.getCourses().add(c);
 9                 }
10             }
11
12         }

注意:Set 中添加某个对象,无论添加多少次,最终只会保留一个该对象(的引用)。同时,保留的是第一次添加的那一个。Set集合是无序的不可重复的。

2)打印输出学生选的课程

1 //输出学生选的课程
2         for(Course c:li.stu.getCourses()){
3             System.out.println(c.getId()+" "+c.getName());
4
5         }

注意:循环遍历Set中的每一个元素只能用foreach或iterator,不能像List一样用get()方法。因为是无序的每次的输出结果都有些差别。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

总结:

1、Set没有像List中set()方法一样就修改,因为List是有序的,可以指定位置,而Set是无序的,可以用循环遍历方式修改。

2、查询遍历时,Set不能用get()方法去获取,因为无序没有指定索引ID,但可以使用foreach和iterator来遍历,但是每次遍历出来可能顺序都不一样,还是因为无序造成的。

3、Set中的size(),add(),addAll(),remove(),removeAll()与List类似。

4、Set还可以添加null(但只能添加一个null,因为不重复);



本篇主要讲述了List和Set的基本操作:增删改查,下一篇我将介绍Map接口的基本操作,有兴趣的小伙伴可以加一下方的"关注"哦!博主正在努力加载中。。。。。。

时间: 2024-10-12 17:52:14

浅入深出之Java集合框架(上)的相关文章

浅入深出之Java集合框架(下)

Java中的集合框架(下) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,哈哈这篇其实也还是基础,惊不惊喜意不意外 ̄▽ ̄ 写文真的好累,懒得写了.. 温馨提醒:建议从(上)开始看哦~ 目 录 浅入深出之Java集合框架(上) 浅入深出之Java集合框架(中)   浅入深出之Java集合框架(下) 前 言 在<浅入深出之Java集合框架(中) >中介绍了Map接口的基本操作.使用的示例是在<浅入深出之Java集合框架(上)>中的模拟学

浅入深出之Java集合框架(中)

Java中的集合框架(中) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架(下)>. 目 录 浅入深出之Java集合框架(上) 浅入深出之Java集合框架(中)   浅入深出之Java集合框架(下) 努力赶制中..关注后更新会提醒哦! 前 言 在<浅入深出之Java集合框架(上)>中介绍了List接口和Set接口的基本操作,在这篇文章中,我将介绍关于Map接口的基

浅入深出ElasticSearch构建高性能搜索架构

浅入深出ElasticSearch构建高性能搜索架构  课程学习地址:http://www.xuetuwuyou.com/course/161 课程出自学途无忧网:http://www.xuetuwuyou.com 一.课程用到的软件 ElasticSearch5.0.0 Spring Tool Suite 3.8.2.RELEASE Maven3.0.5 Spring4 Netty4 Hadoop2.7.1 Kibana5.0 JDK1.8.0_111 二.课程目标 1.快速学习Elastic

『浅入深出』MySQL 中事务的实现

在关系型数据库中,事务的重要性不言而喻,只要对数据库稍有了解的人都知道事务具有 ACID 四个基本属性,而我们不知道的可能就是数据库是如何实现这四个属性的:在这篇文章中,我们将对事务的实现进行分析,尝试理解数据库是如何实现事务的,当然我们也会在文章中简单对 MySQL 中对 ACID 的实现进行简单的介绍. 事务其实就是并发控制的基本单位:相信我们都知道,事务是一个序列操作,其中的操作要么都执行,要么都不执行,它是一个不可分割的工作单位:数据库事务的 ACID 四大特性是事务的基础,了解了 AC

浅入深出Vue:第一个页面

今天正式开始入门篇,也就是实战了~ 首先我们是要做一个博客网站,UI 框架采用江湖传闻中的 ElementUI,今天我们就来利用它确定我们博客网站的基本布局吧. 准备工作 新建一个vue项目(可以参考基础篇里的搭建方法,也可以参考官网现在最近的 Vue CLI 3.x进行可视化创建和管理 安装 vue-router 安装 elementui 以上的操作都可以在之前的博文中(基础篇)找到完整步骤,这里就不重复了. 我们做完准备工作之后,目录结构如下: 我们来看看这个目录: |--public 公共

浅入深出Vue:工具准备之WebStorm安装配置

浅入深出Vue之工具准备(一):WebStorm安装配置 工欲善其事必先利其器,让我们先做好准备工作吧 导航篇 WebStorm安装配置 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版本的WebStorm 安装 下载后即可食用,此步骤与正常软件安装并无二样. 若有固态硬盘,尽可能安装在固态硬盘上,物理加速一下~ 按照自己的系统来勾选32位还是64位,若羽的机器装的是64位系统,因此勾选的是64位.另外为了防止本机没有JetBrains系列所需的JRE环境,建议直接勾选即可. 接下

Android NDK编程浅入深出之--Android.mk

    Android.mk Android.mk是一个向Android NDK构建系统描述NDK项目的GUN Makefile片段.它是每一个NDK项目的必备组件.构建系统希望它出现在jni子目录中.下面是hello-jni项目中Android.mk文件的内容. # Copyright (C) 2009 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License

浅入深出的理解了盒模型,哈哈哈

css盒子模型原理: 在网页设计中常听的属性名:内容(content).填充/内边距(padding).边框(border).外边距(margin), CSS盒子模式都具备这些属性. 这些属性我们可以把它转移到我们日常生活中的盒子(箱子)上来理解,日常生活中所见的盒子也就是能装东西的一种箱子,也具有这些属性,所以叫它盒子模式. CSS中, Box Model叫盒子模型(或框模型),Box Model规定了元素内容(element content).内边距(padding).边框(border)

浅入深出ETCD之【集群部署与golang客户端使用】

前言 之前说了etcd的简介,命令行使用,一些基本原理.这次来说说现实一点的集群部署和golang版本的客户端使用.因为在实际使用过程中,etcd的节点肯定是需要2N+1个进行部署的,所以有必要说明一下集群的部署. 集群部署 网上有很多集群部署的教程,有的很复杂,其实对于我们实际使用来说,其实配置并不复杂,下面举例一种最简单的集群配置.(简单到你想不到~) 下载 https://github.com/etcd-io/etcd/releases 还是在github上面找到需要下载的版本 我使用的是