Java 集合全教程—List

news2024/10/9 12:30:14

Java 集合全教程_Doker 多克的博客-CSDN博客

Java 集合全教程—Set 接口_Doker 多克的博客-CSDN博客

一、概述

列表是一个有序的集合(有时称为序列)。列表可能包含重复的元素。除了从Collection继承的操作外,List接口还包括以下操作:

  • 位置访问-根据元素在列表中的数字位置来操作元素。这包括get、set、add、addAll和remove等方法。
  • 搜索-在列表中搜索指定的对象并返回其数字位置。搜索方法包括indexOf和lastIndexOf。
  • 迭代-扩展了Iterator语义,以利用列表的顺序性。listIterator方法提供了这种行为。
  • 范围视图-子列表方法对列表执行任意范围操作。

Java平台包含两个通用的List实现。ArrayList通常是性能更好的实现,LinkedList在某些情况下提供更好的性能。

二、集合操作

从Collection继承的操作都按照您期望的方式进行,假设您已经熟悉它们。如果您不熟悉《收藏》中的它们,现在是阅读《收藏界面》部分的好时机。移除操作总是从列表中移除指定元素的第一个出现。add和addAll操作总是将新元素追加到列表的末尾。因此,下面的习语将一个列表连接到另一个列表。

list1.addAll(list2);

这是这个习惯用法的一种非破坏性形式,它生成第三个列表,该列表由附加在第一个列表后面的第二个列表组成。

List<Type> list3 = new ArrayList<Type>(list1);
list3.addAll(list2);

请注意,该习语以其无损的形式利用了ArrayList的标准转换构造函数。
下面是一个示例(JDK 8及更高版本),它将一些名称聚合到List中:

List<String> list = people.stream()
.map(Person::getName)
.collect(Collectors.toList());

与Set接口一样,List加强了对equals和hashCode方法的要求,因此可以比较两个List对象的逻辑相等性,而不考虑它们的实现类。如果两个List对象以相同的顺序包含相同的元素,则它们是相等的。

三、操作接口和搜索操作

基本的接口操作是get, set, add and remove。(set和remove操作返回被覆盖或删除的旧值。)其他操作(indexOf和lastIndexOf)返回列表中指定元素的第一个或最后一个索引。
addAll操作从指定位置开始插入指定集合的所有元素。元素是按照指定集合的迭代器返回的顺序插入的。此调用是Collection的addAll操作的位置访问模拟。
这里有一个小方法来交换List中的两个索引值:

public static <E> void swap(List<E> a, int i, int j) {
    E tmp = a.get(i);
    a.set(i, a.get(j));
    a.set(j, tmp);
}

当然,有一个很大的区别。这是一个多态算法:它交换任何List中的两个元素,而不管其实现类型如何。下面是另一个多态算法,它使用前面的交换方法:

public static void shuffle(List<?> list, Random rnd) {
    for (int i = list.size(); i > 1; i--)
        swap(list, i - 1, rnd.nextInt(i));
}

该算法包含在Java平台的Collections类中,它使用指定的随机性源随机排列指定的列表。这有点微妙:它从底部向上运行列表,重复地将随机选择的元素交换到当前位置。与大多数天真的洗牌尝试不同,它是公平的(假设随机性来源不带偏见,所有排列的可能性都相等)和快速的(需要恰好list.size()-1交换)。以下程序使用此算法以随机顺序打印参数列表中的单词。

import java.util.*;

public class Shuffle {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (String a : args)
            list.add(a);
        Collections.shuffle(list, new Random());
        System.out.println(list);
    }
}

事实上,这个程序可以做得更短更快。Arrays类有一个名为asList的静态工厂方法,它允许将数组视为List。此方法不复制数组。列表中的更改会写入到数组中,反之亦然。生成的List不是通用List实现,因为它没有实现(可选)添加和删除操作:数组的大小不可调整。利用Arrays.asList并调用shuffle的库版本(使用默认的随机性源),您可以得到以下小程序,其行为与前一个程序相同:

import java.util.*;

public class Shuffle {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(args);
        Collections.shuffle(list);
        System.out.println(list);
    }
}

四、Iterators

正如您所期望的那样,List的迭代器操作返回的Iterator按正确的顺序返回列表中的元素。List还提供了一个更丰富的迭代器,称为ListIterator,它允许您在任意方向遍历列表,在迭代过程中修改列表,并获得迭代器的当前位置。
ListIterator从Iterator继承的三个方法(hasNext、next和remove)在两个接口中做的事情完全相同。hasPrevious和previous操作与hasNext和next完全类似。前者的操作指的是(隐式)游标之前的元素,而后者指的是游标之后的元素。上一个操作向后移动光标,而下一个操作向前移动光标。
以下是在list中向后迭代的标准习惯用法:

for (ListIterator<Type> it = list.listIterator(list.size()); it.hasPrevious(); ) {
    Type t = it.previous();
    ...
}

注意前面习语中listIterator的参数。List接口有两种形式的listIterator方法。不带参数的表单返回位于列表开头的ListIterator;带有int参数的表单返回位于指定索引处的ListIterator。索引指的是对next的初始调用将返回的元素。对previor的初始调用将返回索引为index-1的元素。在长度为n的列表中,索引有n+1个有效值,从0到n,包括0到n。
直观地说,光标总是在两个元素之间——一个是通过调用前一个返回的元素,另一个是调用下一个返回。n+1个有效索引值对应于元素之间的n+1个间隙,从第一个元素之前的间隙到最后一个元素之后的间隙。下图显示了包含四个元素的列表中可能的五个光标位置:

对下一个和上一个的调用可能是混合的,但您必须小心一点。对上一个的第一次调用返回与对下一个的最后一次调用相同的元素。类似地,在对先前的一系列调用之后对next的第一次调用返回与对先前的最后一次调用相同的元素。
毫不奇怪,nextIndex方法返回将由后续调用返回到next的元素的索引,previousIndex返回将由随后调用返回到previous的元素的指数。这些调用通常用于报告找到某个对象的位置,或者记录ListIterator的位置,以便可以创建另一个具有相同位置的ListIterater。
nextIndex返回的数字总是比previousIndex返回的数字大一也就不足为奇了。这意味着两种边界情况的行为:(1)当光标位于初始元素之前时调用previousIndex返回-1;(2)当光标在最终元素之后时调用nextIndex返回list.size()。为了使这一切具体化,下面是List.indexOf的一个可能实现。

public int indexOf(E e) {
    for (ListIterator<E> it = listIterator(); it.hasNext(); )
        if (e == null ? it.next() == null : e.equals(it.next()))
            return it.previousIndex();
    // Element not found
    return -1;
}

 请注意,indexOf方法返回它.previousIndex(),即使它正向遍历列表。原因是it.nextIndex()将返回我们要检查的元素的索引,而我们希望返回我们刚刚检查的元素索引。
Iterator接口提供了删除操作,用于从集合中删除next返回的最后一个元素。对于ListIterator,此操作将删除next或previor返回的最后一个元素。ListIterator接口提供了两个额外的操作来修改列表集和添加。set方法用指定的元素覆盖next或previor返回的最后一个元素。以下多态算法使用set将一个指定值的所有出现替换为另一个。

public static <E> void replace(List<E> list, E val, E newVal) {
    for (ListIterator<E> it = list.listIterator(); it.hasNext(); )
        if (val == null ? it.next() == null : val.equals(it.next()))
            it.set(newVal);
}

这个例子中唯一的棘手之处是val和it.next之间的相等性测试。您需要对null的val值进行特殊处理,以防止出现NullPointerException。
add方法在当前光标位置之前立即向列表中插入一个新元素。下面的多态算法说明了这种方法,用指定列表中包含的值序列替换指定值的所有出现。

 public static <E> 
    void replace(List<E> list, E val, List<? extends E> newVals) {
    for (ListIterator<E> it = list.listIterator(); it.hasNext(); ){
        if (val == null ? it.next() == null : val.equals(it.next())) {
            it.remove();
            for (E e : newVals)
                it.add(e);
        }
    }
}

五、Range-View操作

Range-View操作subList(int fromIndex,int to Index)返回此列表中索引范围从fromIndex(包含)到toIndex(排除)的部分的列表视图。这个半开放范围反映了典型的for循环。

for (int i = fromIndex; i < toIndex; i++) {
    ...
}

 正如术语视图所暗示的,返回的List由调用子List的List备份,因此前者中的更改反映在后者中。
这种方法消除了对显式范围运算(通常存在于数组中)的需要。通过传递子列表视图而不是整个列表,任何需要列表的操作都可以用作范围操作。例如,下面的习惯用法从列表中删除一系列元素。

list.subList(fromIndex, toIndex).clear();

可以构造类似的习惯用法来搜索范围内的元素。

int i = list.subList(fromIndex, toIndex).indexOf(o);
int j = list.subList(fromIndex, toIndex).lastIndexOf(o);

 请注意,前面的习惯用法返回子列表中找到的元素的索引,而不是backingList中的索引。
任何对List进行操作的多态算法,例如replace和shuffle示例,都可以使用subList返回的List。
这里有一个多态算法,其实现使用subList来处理牌组中的手牌。也就是说,它返回一个新的List(“hand”),其中包含从指定List(“deck”)末尾获取的指定数量的元素。将手上返回的元素从甲板上移除。

    public static <E> List<E> dealHand(List<E> deck, int n) {
    int deckSize = deck.size();
    List<E> handView = deck.subList(deckSize - n, deckSize);
    List<E> hand = new ArrayList<E>(handView);
    handView.clear();
    return hand;
}

 请注意,此算法将手从牌组的末端移除。对于许多常见的List实现(如ArrayList),从列表末尾移除元素的性能要比从开头移除元素好得多。
下面是一个程序,它使用dealHand方法与Collections.shuffle组合,从普通的52副牌组生成手牌。该程序采用两个命令行参数:(1)要发牌的手数和(2)每只手牌的牌数。

import java.util.*;

public class Deal {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: Deal hands cards");
            return;
        }
        int numHands = Integer.parseInt(args[0]);
        int cardsPerHand = Integer.parseInt(args[1]);
    
        // Make a normal 52-card deck.
        String[] suit = new String[] {
            "spades", "hearts", 
            "diamonds", "clubs" 
        };
        String[] rank = new String[] {
            "ace", "2", "3", "4",
            "5", "6", "7", "8", "9", "10", 
            "jack", "queen", "king" 
        };

        List<String> deck = new ArrayList<String>();
        for (int i = 0; i < suit.length; i++)
            for (int j = 0; j < rank.length; j++)
                deck.add(rank[j] + " of " + suit[i]);
    
        // Shuffle the deck.
        Collections.shuffle(deck);
    
        if (numHands * cardsPerHand > deck.size()) {
            System.out.println("Not enough cards.");
            return;
        }
    
        for (int i = 0; i < numHands; i++)
            System.out.println(dealHand(deck, cardsPerHand));
    }
  
    public static <E> List<E> dealHand(List<E> deck, int n) {
        int deckSize = deck.size();
        List<E> handView = deck.subList(deckSize - n, deckSize);
        List<E> hand = new ArrayList<E>(handView);
        handView.clear();
        return hand;
    }
}

运行程序会产生如下输出:

% java Deal 4 5

[8 of hearts, jack of spades, 3 of spades, 4 of spades,
    king of diamonds]
[4 of diamonds, ace of clubs, 6 of clubs, jack of hearts,
    queen of hearts]
[7 of spades, 5 of spades, 2 of diamonds, queen of diamonds,
    9 of clubs]
[8 of spades, 6 of diamonds, ace of spades, 3 of hearts,
    ace of hearts]

尽管subList操作非常强大,但在使用它时必须小心。如果以除返回的List之外的任何方式将元素添加到支持List或从支持List中删除元素,则subList返回的List的语义将变得未定义。因此,强烈建议您仅将subList返回的List用作临时对象,以便对支持List执行一个或一系列范围操作。使用子列表实例的时间越长,通过直接或通过另一个子列表对象修改支持列表来破坏它的可能性就越大。请注意,修改子列表的子列表并继续使用原始子列表是合法的(尽管不是同时使用)

 六、List 算法

Collections类中的大多数多态算法都专门应用于List。有了所有这些算法,就可以很容易地操作列表。以下是这些算法的摘要,在“算法”部分将对其进行更详细的描述:

  • sort-使用合并排序算法对List进行排序,该算法提供了快速、稳定的排序。(稳定排序是指不重新排序相等元素的排序。)
  • shuffle-随机排列列表中的元素。
  • reverse-反转列表中元素的顺序。
  • rotate-将列表中的所有元素旋转指定的距离。
  • swap-交换列表中指定位置的元素。
  • replaceAll-用另一个指定值替换所有出现的值。
  • fill-用指定的值覆盖列表中的每个元素。
  • copy-将源列表复制到目标列表中。
  • binarySearch-使用二进制搜索算法在有序列表中搜索元素。
  • indexOfSubList-返回一个列表的第一个子列表与另一个列表相等的索引。
  • lastIndexOfSubList-返回一个列表的最后一个子列表的索引,该子列表等于另一个列表。

📢文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群💪💪💪
📢首发CSDN博客,创作不易,如果觉得文章不错,可以点赞👍收藏📁评论📒
📢你的支持和鼓励是我创作的动力❗❗❗ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/623056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java抽象类介绍

1 问题 声明一个名为Employee的抽象类&#xff0c;其中包含name(姓名)和sex(性别)两个String类型的私有属性&#xff0c;并声明一个继承于Employee抽象类的子类Teacher。 2 方法 2.1 定义一个抽象类&#xff1a;Employee。 2.2 为Employee类设计一个抽象方法。 2.3实现抽象类Em…

vue对接海康摄像头,配合ifarme进行展示。给ifarme点击事件(消除ifarme事件,因为ifarme没有点击事件)

1、在public文件夹下建一个文件ifarme.index&#xff0c;和index.html同级。 <!doctype html> <html><head><title></title><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><meta http-equi…

【熬夜送书 | 第三期】清华社赞助 | 《Java系列丛书》

前言 Java作为一门主流语言&#xff0c;它与其他语言相比&#xff0c;有什么优势呢? Java 是一种广泛使用的高级编程语言&#xff0c;具有多项特性&#xff1a; 1.简单易学&#xff1a;Java 语言的语法与 C 相似&#xff0c;但删掉了复杂的指针、运算符重载等内容&#xff0…

C++继承相关内容(三)

目录 一.单例模式和相关习题 1.不能在外部环境创建该类对象 方法&#xff1a; 代码&#xff1a; 2.创建一个不能被继承的类 方法&#xff1a; 3.创建一个不能被继承&#xff0c;但是可以在外部环境中创建该类对象 方法&#xff1a; ​编辑 4.一个能被继承的类&#xf…

【WinForm】WinForm常见窗体技术汇总

文章目录 前言一、窗体调用外部程序与渐变窗体1、效果2、界面设计3、代码 二、按回车键跳转窗体中的光标焦点1、效果2、界面设计3、代码 三、剪切板操作1、效果2、界面设计3、代码 四、实现拖放操作1、效果2、界面设计3、代码 五、移动的窗体1、效果2、界面设计3、代码 六、抓不…

聚观早报 | OpenAI 没有上市计划;马斯克称未来房价下跌将加速

今日要闻&#xff1a;OpenAI 没有上市计划&#xff1b;马斯克称未来房价下跌将加速&#xff1b;Coinbase被SEC起诉&#xff0c;股价闪崩&#xff1b;库克&#xff1a;苹果正密切关注ChatGPT等&#xff1b;推特正致力于开发视频直播产品 OpenAI没有上市计划 当地时间周二&…

068:cesium lookAtTransform围绕一个固定点上下左右旋转查看

第068个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中查看一个固定的点的情况,从上下左右不同的维度进行查看。这里面使用lookAtTransform这个操作函数。lookAtTransform(transform, offset),这里的offset偏移量可以是笛卡尔坐标或航向/俯仰/范围。 直接复制下面…

Java集合常见面试题集锦

1、介绍Collection框架的结构 集合是Java中的一个非常重要的一个知识点&#xff0c;主要分为List、Set、Map、Queue三大数据结构。它们在Java中的结构关系如下&#xff1a; Collection接口是List、Set、Queue的父级接口。 Set接口有两个常用的实现类&#xff1a;HashSet和Tre…

libmodbus编程笔记

一 基础知识 地址映射值 Modbus寄存器 Modbus寄存器地址分配 Modbus ASCII消息帧格式 Modbus RTU帧格式 Modbus RTU相邻帧间隔 Modbus寻址范围 PDU与ADU的关系 Modbus TCP/IP ADU与PDU的关系 Modbus TCP/IP与Modbus串行消息构成对比 Modbus TCP/IP协议最大帧数据长度为260字…

人工智能-实验四

第四次实验 一.实验目的 ​ 了解深度学习的基本原理。能够使用深度学习开源工具。学习使用深度学习算法求解实际问题。 二.实验原理 1.深度学习概述 ​ 深度学习源于人工神经网络&#xff0c;本质是构建多层隐藏层的人工神经网络&#xff0c;通过卷积&#xff0c;池化&…

【2 微信小程序学习 - 小程序的架构.配置.app与page】

1 小程序的架构模型 为了避免卡顿,优化性能,小程序使用双线程模型. 可以理解为创建了两个webview,一个负责渲染界面,一个负责js脚本处理,通过微信客户端的native进行中转交互. 2 小程序的配置文件 在多人开发中,一般不修改project.config.json避免冲突 ,而是单人修改project…

Intradeco通过适用于Excel的Liquid UI自动执行SAP MM并节省80%的处理时间

背景 Intradeco为服装制造提供整体方法&#xff0c;涵盖所有阶段&#xff1a;从构思阶段到最终产品分销。它已发展成为一家全球垂直制造公司&#xff0c;客户遍布美国、墨西哥和加拿大。 挑战 提高运营效率 原因&#xff1a;人员必须浏览多个 SAP 事务才能为新材料创建采购订单…

2023年牛客网最新Java面试八股文附答案整理(不管工作几年都可以看看)

很多人都说今年对于 IT 行业根本没有所谓的“金三银四”“金九银十”。在各大招聘网站或者软件上不管是大厂还是中小公司大多都是挂个招聘需求&#xff0c;实际并不招人&#xff1b;在行业内的程序员基本都已经感受到了任老前段时间口中所谓的“寒气”。 虽然事实确实是如此&a…

学顶教育:初级会计师领取证书有关事项

初级会计师职称证书是国家组织考试后颁发的专业技术资格证书&#xff0c;与纸质证书和电子证书具有同等法律效力。 考取初级会计师职称证书的有关事项如下&#xff1a; 1、领取方式 初级会计职称证书的领取方式有两种&#xff1a;现场领取和邮寄领取。 考生可任选其一。 部分…

浪涌保护器和避雷器的区别

线路在使用过程中&#xff0c;由于短路或雷击&#xff0c;会突然产生巨大的能量。一旦这种能量通过线路进入家庭或其他电力线&#xff0c;就会造成设备烧毁&#xff0c;造成生命和财产损失。直流电涌保护器可以通过保护组件立即将巨大的能量吸入地面端子&#xff0c;从而保护您…

[架构之路-207]- 常见的需求分析技术:实用的需求分析与建模详解过程(实操性强)

目录 1.1 需求分析建模的要点与误区 1.1.1 需求分析到底做什么 1.1.1.1 分解的方法 1.1.1.2 提炼、合并、重组 1.1.1.3 消除矛盾 1.1.2 建模的目标和要点 1.1.2.1 建模的目的 1.1.2.2 建模的要点与原则 1.1.3 选择建模工具的要点 1.1.3.1 正确认识建模方法论 1.1.3.…

肠道菌群检测在临床感染判别中的应用

谷禾健康 感染是人类面临的健康威胁之一。各种病原体&#xff0c;如细菌、病毒、真菌、寄生虫等&#xff0c;存在于我们日常接触的环境、物品、食物等中。一些常见的感染病例包括感冒、流感、腹泻、组织器官或血液感染等&#xff0c;在全球范围内广泛传播。这些疾病的传播方式多…

MAYA活塞动画

给组打关键 让下面带动上面一起运动 创建定位器 放在中间 创建两个定位器 一个定位器放在连动秆下面&#xff0c;让定位跟物体一块动 创建目标约束 完成

python基础----07-----异常、模块、包

一 了解异常 当检测到一个错误时&#xff0c;Python解释 器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的“异常”&#xff0c;也就是我们常说的BUG。 二 异常的捕获 当我们的程序遇到了BUG&#xff0c;那么接下来有两种情况&#xff1a; …

AcWing算法提高课-1.3.14开心的金明

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 本题链接&#xff08;AcWing&#xff09; 点这里 题目描述 金明今天很开心&#xff0c;家里购置的新房就要领钥匙了&#xff0c;新房里有一间他自己专用的很宽敞的房间。 更让他高兴的是&…