注册 登录
Java基础教程

第一章: 开启Java学习之旅

第二章: 掌握计算机基础知识

第三章: 掌握命令行基础知识

第四章: 我的第一个Java程序

第五章: Java编程必备基础

第六章: Java编程的核心:控制结构

第七章: Java面向对象基础

第八章: Java面向对象进阶

第九章: Java字符串类型

第十章: Java数组与数据结构

第十一章: Java高级数据结构

第十二章: Java并发编程基础

首页 > Java基础教程 > 第十一章: Java高级数据结构 > 11.2节: Collection容器

11.2节: Collection容器

薯条老师 2021-12-28 11:54:20 261440 0

编辑 收藏

广州番禺Python, Java小班周末班培训

薯条老师的线下Python小班办得很好,学员的平均就业薪资有11K。线下小班培训的课程有Python爬虫,Python后端开发,Python办公自动化,Python大数据分析,Python量化投资,Java中高级后端开发。授课详情请点击:http://chipscoco.com/?cate=6

11.2.1 Collection中的List接口

Collection中的List接口是对线性表的行为的抽象。在Java中提供了ArrayList类,以及LinkedList类,它们都实现了List接口提供的方法,其中ArrayList基于顺序表,而LinkedList基于链表。

对线性结构,顺序表结构,链表结构不是很熟悉的同学,可以复习第十章的内容。

使用Java中的容器,需通过<>符号来声明容器中的对象的类型,例如定义一个管理字符串对象的容器,我们可以这么定义:

// 定义一个管理字符串对象的顺序表容器,使用默认的容器大小16
ArrayList<String> names = new ArrayList<String>();

也可以在定义时显示指定容器的大小:

// 定义一个管理int数组对象的顺序表容器,将容器大小初始化为20
ArrayList<int []> names = new ArrayList<int []>(20);

读者需注意,在代码中使用ArrayList或LinkedList, 需要先通过import语句进行导入。以下为导入ArrayList和LinkedList的语法:

// 在程序中导入ArrayList和LinkedList的语法
import java.util.ArrayList;
import java.util.LinkedList;

知道怎么定义和导入容器以后,我们接下来掌握ArrayList与LinkedList的常用操作方法。下表所示为ArrayList的常用添加操作:

方法名

描述

boolean add(E e)

将对象e添加到容器尾部,返回值为布尔类型,返回true表示添加成功,返回false表示添加失败。这里的E泛指任意类型,定义容器时声明什么样的对象类型,E就是什么类型。

boolean add(int index, E e)

  将对象e添加到索引index所指定的位置,index必须小等于顺序表的长度。返回值同add方法。

boolean addAll(Collection c)

  将集合c中的所有对象添加至容器尾部。返回值同add方法。

boolean addAll(int index, Collection c)

 将容器c添加到索引index所指定的位置,index必须小于等于顺序表的长度。返回值同add方法。

代码实例-ArrayList的添加操作:

import java.util.ArrayList;
 
public class HelloJava{
    public  static void main(String[] args) {
        // 定义一个管理字符串对象的ArrayList容器
        ArrayList<String> englishNames = new ArrayList<String>();
        // 将isa添加到尾部
        englishNames.add("Lisa");
        // 将Lohan添加到第一个位置,顺序表中的index从0开始编号,0表示第一个位置
        englishNames.add(0, "Lohan");
        // 定义一个管理字符串对象的ArrayList容器
        ArrayList<String> names = new ArrayList<String>();
        // 将englishNames容器中的所有元素添加到names容器
        names.addAll(englishNames);
        System.out.println(names);
    }
}

ArrayList的常用查询操作:

方法名

描述

Object get(int index)

  获取容器中的index位置的对象。

int indexOf(Object o)

  返回容器对象o在容器中的第一次出现的位置索引,如果不存在则返回-1。

int lastIndexOf(Object o)

  lastIndexOf方法是返回对象o在容器中的最后一次出现的位置索引,如果不存在则返回-1。

boolean contains(Object o)

 该方法用来查询容器中是否包含对象o,如果包含就返回true,否则返回false。

代码实例-ArrayList的查询操作:

import java.util.ArrayList;
 
public class HelloJava{
    public  static void main(String[] args) {
        // 定义一个管理字符串对象的ArrayList容器
        ArrayList<String> names = new ArrayList<String>();
        names.add("Lohan");
        // 获取索引0位置的对象
        String name = names.get(0);
        // 查询names容器中Lisa对象的索引位置,如果不存在则返回-1
        int index = names.indexOf("Lisa");
        System.out.println(index);
    }
}

ArrayList的常用删除操作:

方法名

描述

boolean remove(Object o)

  通过对象的equals方法来判断是否相等,如果相等就从容器中删除。读者需注意,该方法只会删除匹配的第一个元素。

void clear()

  将容器中的对象全部清除

代码实例-ArrayList的删除操作:

import java.util.ArrayList;
 
public class HelloJava{
    public  static void main(String[] args) {
 
        // 定义一个管理字符串对象的ArrayList容器
        ArrayList<String> names = new ArrayList<String>();
        names.add("Lohan");
        names.add("Lisa");
        String name = "Lisa";
        if (names.contains(name)) {
            // 如果names容器中包含Lisa,就将其移除
            names.remove(name);
        }
        System.out.println(names);
        // 不再需要names容器的时候,应该执行clear方法,将容器清空
        names.clear();
        System.out.println(names);
    }
}

ArrayList的其它常用操作:

方法名

描述

int size()

 返回容器中的元素数目。

boolean isEmpty()

  判断容器是否为空,返回true则表示容器为空,否则表示容器非空。

boolean equals()

 判断容器是否相等,返回true则表示相等,否则不相等。比较容器是否相等,实质是逐一通过容器元素的equals方法来进行比较。

Object[] toArray()

 将容器转换为数组。

以上方法均适用于LinkedList,因为LinkedList也实现了List接口。读者将以上代码实例中的ArrayList替换为LinkedList, 可直接编译执行。虽然ArrayList与LinkedList都实现了List接口,但它们的使用场景是不一样的。ArrayList基于顺序表,顺序表适用于对元素进行随机访问和在末尾添加元素的场景,而LinkedList基于链表,链表适用于对容器中的元素进行频繁添加或删除的场景。顺序表在内存中是连续存储,如果在容器的首尾之间的位置添加或删除元素,那么容器的中的其它所有元素需要往前或往后进行移动。而链表通常为非连续存储,在添加或删除元素时,只需改变前后节点链接的地址。深入理解顺序表和链表,需要读者进一步学习数据结构这门课程。

11.2.2 Queue和Stack

Queue即队列,队列是基于FIFO 的数据结构,FIFO表示先进先出。队列的基本操作有入队和出队,入队是从队尾开始,而出队是从队首出去,这种操作就像我们在商场中排队一样,排队时从队尾开始排,每次先出去的是排在队伍最前面的那个人。队列的逻辑结构和操作如下图所示:

图片.png 

Stack即栈,栈是基于LIFO的数据结构,LIFO表示后进先出。栈这种数据结构类似于装衣服的箱子:后面放的衣服叠在最上面,每次取衣服的时候,首先看到的是最后面放的衣服。栈的基本操作有入栈和出栈,其逻辑结构和操作如下图所示:

图片.png 

读者可以把栈结构中的栈底理解为箱子的箱底,而栈顶指向的永远是箱子中最后放的衣服。队列和栈的具体实现不再细述,我们现在来学习Queue和Stack的常用操作方法。在程序中使用Queue和Stack,需要从java.util进行导入,导入的语法示例:import java.util.Queue;Queue在Java中是一个接口,其包含以下几个方法:

方法名

描述

boolean add(E e)

将元素e添加到队尾,添加成功返回true,否则返回false。在队列已满的情况下添加元素会抛出异常。

E remove()

  获取队首的元素并将其从队列中删除。队列为空时会抛出异常。

boolean offer(E e)

  将元素e添加到队尾,添加成功返回true,否则返回false。在队列已满的情况下添加元素会返回false。

E peek()

 获取队首的元素但不删除。队列为空时返回null。

E poll()

 获取队首的元素并将其从队列中删除。队列为空时返回null。

Java中的LinkedList实现了Queue接口,以下为代码实例:

import java.util.LinkedList;
import java.util.Queue;
public class HelloJava{
    public  static void main(String[] args) {
    Queue<String> names = new LinkedList<String>();
    // 将Lohan插入到队尾
    names.offer("Lohan");
    // 将Lisa插入到队尾
    names.offer("Lisa");
    // 取出队首的元素并删除
    String name = names.poll();
    System.out.println(name);
    }
}

Stack是一个类,其继承于Vector, Vector又实现了List接口。以下为Stack类的常用操作方法:

方法名

描述

E push(E item)

将元素item入栈,并返回item。

E pop()

  取出栈顶的元素。栈为空时会抛出异常。

E peek()

  取出栈顶的元素但不删除。栈为空时会抛出异常。

boolean empty()

 该方法用来测试栈是否为空

代码实例-装衣服的箱子:

import java.util.Stack;
public class HelloJava{
    public  static void main(String[] args) {
        Stack<String> box = new Stack<String>();
        // 往箱子里放入衬衣
        box.push("shirt");
        // 再往箱子里放入外套
        box.push("overcoat");
        // 打开箱子取衣服的时候,先看到的是外套,这即是LIFO,后进先出
        String clothing = box.peek();
        System.out.println(clothing);
    }

11.2.3去重的数据集合Set

我们在前面两节学的List及其子类型有一个很大的共性,这些容器均支持添加重复元素。

在某些场景中,我们需要的是一个不包含重复元素的数据集合,比如实现一个网页下载器。网页下载器从队列中取出种子URL,然后下载对应的网页,由于队列结构允许存在重复的元素,所以在下载过程中,可能会进行重复下载,从而浪费系统资源。

队列等结构虽然允许添加重复的元素,但是我们可以在代码中进行判断,如果元素已存在就不添加。代码实例-实现一个去重的队列:

import java.util.LinkedList;
// 定义一个去重的队列UniqueQueue
class UniqueQueue<E> extends LinkedList<E> {
    @Override
    public boolean add(E e) {
        // 如果元素已存在,就直接返回false
        if (this.contains(e)){
            return false;
        } else {
            return super.add(e);
        }
    }
}


public class HelloJava{
    public  static void main(String[] args) {
        LinkedList<String> urls = new UniqueQueue<String>();
        urls.add("htp://www.chipscoco.com");
        urls.add("htp://www.chipscoco.com");
        urls.add("htp://www.chipscoco.com");
        // 虽然添加了3次相同的url:htp://www.chipscoco.com
        // 但在输出时指看到一个,说明进行了排重处理
        System.out.println(urls);
    }
}

以上代码通过contains方法实现了一个去重的队列UniqueQueue,但是这种实现有一个很大的局限性,contains方法是以顺序查找的方式来查找元素是否已存在,如果数据集合很大,那么这样的查找方式性能会很差。

Java中的HashSet容器基于哈希表结构,通过哈希表就可以实现快速排重。哈希表是一种高效的映射结构,在理想情况下,只需计算一次元素的哈希值,就可以快速地查找元素是否存在于数据集合中,即使数据集合中存在百万级,甚至千万级、亿万级的数据量。深入理解哈希表为什么查找速度这么快,需要读者掌握数据结构与算法这门课程。

Java中的HashSet类实现了Set接口,下表为HashSet的常用方法:

方法名

描述

HashSet(int initialCapacity)

HashSet的构造方法,用来构造一个容量为

initialCapacity大小的集合。

boolean add(E e)

  添加元素到集合中,如果元素不存在。返回true表示添加成功,返回false表示添加失败

boolean remove(Object o)

  将指定的元素从集合中删除,返回true表示移除成功,返回false表示移除失败

boolean contains(Object o)

 快速查找指定元素是否存在于集合中,返回true表示存在,返回false表示不存在。

int size()

 返回集合中的元素数目

void clear()

 将集合中的元素全部移除

代码实例-使用HashSet去重:

import java.util.HashSet;
public class HelloJava{
    public  static void main(String[] args) {
       HashSet<String> urls = new HashSet<String>();
       urls.add("http://www.chipscoco.com");
       urls.add("http://www.chipscoco.com");
       urls.add("http://www.chipscoco.com");
       System.out.println(urls);
    }
}

11.2.4 最具实力的小班培训

来这里参加Python和Java小班培训的学员大部分都找到了很好的工作,平均月薪有11K,学得好的同学,拿到的会更高。由于是小班教学,所以薯条老师有精力把每位学员都教好。打算参加线下小班培训的同学,必须遵守薯条老师的学习安排,认真做作业和项目。把知识学好,学扎实,那么找到一份高薪的工作就是很简单的一件事。

(1) Python后端工程师高薪就业班,月薪11K-18K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十五万,免费领取课程大纲
(3) Java后端开发工程师高薪就业班,月薪11K-20K, 免费领取课程大纲
(4) Python大数据分析,量化投资就业班,月薪12K-25K,免费领取课程大纲

扫码免费领取学习资料:

关注微信公众号.jpg








欢迎 发表评论:

请登录

忘记密码我要注册

注册账号

已有账号?请登录