首页 > 编程语言 >浅谈Java容器

浅谈Java容器

时间:2023-07-19 12:33:08浏览次数:40  
标签:容器 Java 浅谈 Map 元素 List 接口 哈希 集合

Java容器

容器类是Java以类库的形式供用户开发程序时可直接使用的各种数据结构。所谓数据结构就是以某种方式将数据组织在一起,并存储在计算机中。数据结构不仅可以存储数据,还支持访问和处理数据的操作。在面向对象思想里,一种数据结构被认为是一个容器。数组是一种简单的数据结构,除数组外Java还以类库的形式提供了许多其他数据结构。这些数据结构通常称为容器类或称集合类。

Java容器框架

Java容器框架中有两个名称分别为CollectionSet的接口,本书将Collection译为容器,而将Set译为集合。Java容器框架提供了一些现成的数据结构可供使用,这些数据结构是可以存储对象的集合,在这里对象也称为元素。从JDK 5开始,容器框架全部采用泛型实现,且都存放在java.util包中。容器框架中的接口及实现这些接口的类的继承关系如图12.1所示。Java容器框架结构由两棵接口树构成,第一棵树根节点为Collection接口,它定义了所有容器的基本操作,如添加、删除、遍历等。它的子接口Set、List等则提供了更加特殊的功能,其中Set的对象用于存储一组不重复的元素集合,而List的对象用于存储一个由元素构成的线性表。第二棵树根节点为Map接口,它保持了“键”到“值”的映射,可以通过键来实现对值的快速访问。

容器框架中的接口和实现接口的类的继承关系:

容器接口Collection

容器接口Collection通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于Set接口和List接口都继承了Collection接口,因此这些方法对集合Set与列表List是通用的。下面给出了Collection<E>接口的常用方法,其中的方法默认为public abstract。由于容器框架全部采用泛型实现,所以我们以泛型的形式给出相应的方法,即带类型参数。

List <E>接口的常用方法

列表接口List

列表接口ListCollection子接口,它是一种包含有序元素的线性表,其中的元素必须按顺序存放,且可重复,也可以是空值null。元素之间的顺序关系可以由添加到列表的先后来决定,也可由元素值的大小来决定。List接口使用下标来访问元素。下标范围为0~size()-1。List接口新增了许多方法,使之能够在列表中根据具体位置添加和删除元素。List<E>接口的主要方法如表所示。方法默认为public abstract

List <E>接口的常用方法:

实现List接口的类主要有两个:链表类LinkedList和数组列表类ArrayList。它们都是线性表。

LinkedList链表类采用链表结构保存对象,使用循环双链表实现List。这种结构向链表中任意位置插入、删除元素时不需要移动其他元素,链表的大小是可以动态增大或减小的,但不具有随机存取特性。

ArrayList数组列表类使用一维数组实现List,该类实现的是可变数组,允许所有元素,包括null。具有随机存取特性,插入、删除元素时需要移动其他元素,当元素很多时插入、删除操作的速度较慢。在向ArrayList中添加元素时,其容量会自动增大,但不能自动缩小,但可以使用trimToSize()方法将数组的容量减小到数组列表的大小。

ArrayList数组列表类使用一维数组实现List,该类实现的是可变数组,允许所有元素,包括null。具有随机存取特性,插入、删除元素时需要移动其他元素,当元素很多时插入、删除操作的速度较慢。在向ArrayList中添加元素时,其容量会自动增大,但不能自动缩小,但可以使用trimToSize()方法将数组的容量减小到数组列表的大小。

下面分别给出了LinkedList<E>类和ArrayList<E>类的构造方法。

LinkedList <E>类的构造方法

LinkedList <E>类的构造方法

使用线性表时通常声明为List <E>类型,然后通过不同的实现类来实例化列表。如:

List<String> List1 = new LinkedList<String>();
List<String> List2 = new ArrayList<String>();

LinkedList <E>类与ArrayList <E>类大部分方法是继承其父类或祖先类,除此之外还各自定义了自己的方法,下面分别给出了LinkedList<E>类与ArrayList<E>类的常用方法。

LinkedList <E>类的常用方法:

ArrayList <E>类的常用方法:

利用LinkedList <E>类构造一个先进后出的堆栈。

package com.demo.seckill;

import java.util.LinkedList;
import java.util.Scanner;


class StringStack {
    private LinkedList<String> Id = new LinkedList<String>();//创建LinkedList对象Id

    public void push(String name) { //入栈操作
        Id.addFirst(name);          //将name添加到链表的头
    }

    public String pop() {           //出栈操作
        return Id.removeFirst();    // 获取并移出堆栈中的第一个元素
    }

    public boolean isEmpty() {      //判断堆栈是否为空
        return Id.isEmpty();
    }
}


public class Map {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        StringStack stack = new StringStack();
        System.out.println("请输人数据(quit结束)");
        while (true) {
            String input = sc.next();   //从键盘输入数据
            if (input.equals("quit"))
                break;
            stack.push(input);  //入栈
        }
        System.out.println("先进后出的顺序:");
        while (!stack.isEmpty())
            System.out.print(stack.pop() + " ");    //出栈
    }
}

集合接口Set

Set是一个不含重复元素的集合接口,它继承自Collection接口,并没有声明其他方法,它的方法都是从Collection接口继承来的。Set集合中的对象不按特定的方式排序,只是简单地把对象加入集合中即可,但加入的对象一定不能重复。集合中元素的顺序与元素加入集合的顺序无关。实现Set接口的两个主要类是哈希集合类HashSet及树集合类TreeSet。

哈希集合类HashSet

哈希集合对所包含元素的访问并不是像线性表一样使用下标,而是根据哈希码来存取集合中的元素。为此先介绍一下哈希码的概念。哈希集合是在元素的存储位置和元素的值k之间建立一个特定的对应关系f,使每个元素与一个唯一的存储位置相对应。因而在查找时,只要根据元素的值k,计算f(k)的值即可,如果此元素在集合中,则必定在存储位置f(k)上,因此不需要与集合中的其他元素进行比较便可直接取得所查的元素。称这个对应关系f为哈希函数,按这种关系建立的表称为哈希表,也称散列表。

HashSet集合类是基于哈希表的Set接口实现的。HashSet根据哈希码来确定元素在集合中的存储位置(即内存地址),因此可以根据哈希码来快速地找到集合中的元素。HashSet集合不保证迭代顺序,但允许元素值为null。在比较两个加入哈希集合HashSet中的元素是否相同时,会先比较哈希码方法hashCode()的返回值是否相同,若相同则再使用equals()方法比较其存储位置(即内存地址),若两者都相同则视为相同的元素。之所以在比较了哈希码之后,还要通过equals()方法进行比较,是因为对不同元素计算出的哈希码可能相同。因此,对于哈希集合来说,若重写了元素对应类的equals()方法或hashCode()方法中的某一个,则必须重写另一个,以保证其判断的一致性。

分别给出了HashSet<E>集合类的构造方法和常用方法。

HashSet <E>集合类的构造方法

说明:构造方法中的上座率也称装填因子,上座率的值为0.0~1.0表示集合的饱和度。当集合中的元素个数超过了容量与上座率的乘积,容量就会自动翻倍。

HashSet <E>集合类的常用方法

说明:输出哈希集合元素时并不一定是按元素的存储顺序输出,因为哈希集合中的元素是没有特定顺序的,若一定要让元素有序输出,则需要使用LinkedHashSet类。

树集合类TreeSet

树集合类TreeSet不仅实现了Set接口,还实现了java.util.SortedSet接口。TreeSet的工作原理与HashSet相似,但TreeSet增加了一个额外步骤,以保证集合中的元素总是处于有序状态。因此,当排序很重要时,就选择TreeSet,否则应选用HashSet。TreeSet<E>类的大多数方法继承自其父类或祖先类。

TreeSet <E>类的构造方法

TreeSet <E>类的新增的方法

映射接口Map

Map是另一种存储数据结构的对象,Map接口与List接口和Set接口有明显的区别。Map中的元素都是成对出现的,它提供了键(key)到值(value)的映射。值是指要存入Map中的元素(对象),在将元素存入Map对象时,需要同时给定一个键,这个键决定了元素在Map中的存储位置。一个键和它对应的值构成一个条目,真正在Map中存储的是这个条目。键很像下标,但在List中下标是整数,而在Map中键可以是任意类型的对象。如果要在Map中检索一个元素,必须提供相应的键,这样就可以通过键访问到其对应元素的值。Map中的每个键都是唯一的,且每个键最多只能映射到一个值。由于Map中存储元素的形式较为特殊,所以Map没有继承Collection接口。表12.13给出Map<K,V>接口的常用方法,其中K表示键的类型,V表示值的类型。因为Map是接口,所以其方法默认为public abstract。

Map <K,V>接口的常用方法

映射接口Map常用的实现类有哈希映射HashMap和树映射TreeMap。HashMap映射是基于哈希表的Map接口的实现类,所以HashMap通过哈希码对其内部的映射关系进行快速查找,因此对于添加和删除映射关系效率较高,并且允许使用null值和null键,但必须保证键的唯一性;而树映射TreeMap中的映射关系存在一定的顺序,如果希望Map映射中的元素也存在一定的顺序,应该使用TreeMap类实现的Map映射,由于TreeMap类实现的Map映射中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是null。

HashMap映射的方法大多是继承自Map接口。

HashMap <K,V>映射常用的构造方法

分别给出了TreeMap<K,V>映射的构造方法和常用方法。

TreeMap <K,V>映射的构造方法

TreeMap <K,V>映射的常用方法

总结

  1. 容器是存储对象的数据结构的集合。容器框架中定义的所有接口和类都存储在java.util包中。

  2. 从容器的当前元素获取其后续元素进行访问的过程称为迭代,迭代也称为遍历。

  3. List的对象用于存储一个由元素构成的线性表;Set的对象是存储一组不重复的元素集合;Map的对象保持了键到值的映射。

  4. List是一种包含有序元素的线性表,其中的元素必须按顺序存放,且可重复,也可以是空值null。实现List接口的类主要有链表类LinkedList和数组列表类ArrayList。

  5. LinkedList是实现List接口的链表类,采用双向链表结构保存元素,访问元素的时间取决于元素在表中所处的位置,但对链表的增长或缩小则没有任何额外的开销。

  6. ArrayList是实现List接口的数组列表类,它使用一维数组实现List,支持元素的快速访问,但在数组的扩展或缩小时则需要额外的系统开销。

  7. Set是一个不含重复元素的集合接口。实现Set接口的两个主要类是哈希集合类HashSet及树集合类TreeSet。

  8. HashSet的工作原理是在哈希集合中元素的“值”与该元素的存储位置之间建立起一种映射关系,这种映射关系称为哈希函数或散列函数,由哈希函数计算出来的数值称为哈希码或散列索引。虽然HashSet中的元素是无序的,但由于HashSet特性还是可以快速地添加或访问其中的元素。

  9. 因为对不同元素计算出的哈希码可能相同,所以判断哈希集合中的元素是否相同时需要同时使用hashCode()方法和equals()方法。

  10. TreeSet类对象中的元素总是有序的,所以当插入元素时需要一定的开销。

  11. Map中的元素都是成对出现的,它提供了键(key)到值(value)的映射。

  12. 映射接口Map常用的实现类有HashMap和TreeMap。HashMap类与TreeMap类的关系如同HashSet与TreeSet的关系一样。

  13. HashMap类是基于哈希表的Map接口的实现,允许使用null值和null键,但必须保证键的唯一性,HashMap是无序的。

  14. TreeMap类中的映射关系存在一定的顺序,不允许键对象是null。TreeMap是有序的。

标签:容器,Java,浅谈,Map,元素,List,接口,哈希,集合
From: https://www.cnblogs.com/yangyezhuang/p/17565263.html

相关文章

  • Java基础入门
    一、注释方式标识符单行注释//多行注释/**/文档注释/***/二、基础1、进制进制前缀二进制0b八进制0十进制无十六进制0x2、数据类型typevarName[=value][{,varName[=value]}];bytenum1=127;shortnum2=32767;intn......
  • mysql 5.7 修改密码 docker 导出容器
    MISCONFRedisisconfiguredtosaveRDBsnapshots,butiscurrentlynotabletopersistondisk.Commandsthatmaymodifythedatasetaredisabled.PleasecheckRedislogsfordetailsabouttheerror updateusersetauthentication_string=password('......
  • Java高并发之CyclicBarrier简介(转)
    原文:https://juejin.cn/post/7209617649885184058作者:xindoo来源:稀土掘金  Java中的CyclicBarrier是一种同步工具,它可以让多个线程在一个屏障处等待,直到所有线程都到达该屏障处后,才能继续执行。CyclicBarrier可以用于协调多个线程的执行,以便它们可以在某个点上同步执行......
  • JavaScript 的优雅编程技巧:Singleton Pattern
    JavaScript的优雅编程技巧:SingletonPattern定义单例模式:保证一个类仅有一个实例,并提供一个访问的全局访问点。特点仅有一个实例对象全局都可访问该实例主动实例化延迟实例化类似单例模式的使用实践jQuery,lodash,moment....电商中的购物车(因为一个用户只有一......
  • javaSe笔试题
    1 ==和equals区别 ......
  • 【Javascript】数组扩展方法:根据key重新分组
    1//数组扩展:根据key重新分组2//field:按什么字段分组3Array.prototype.GroupByKey=function(field)4{5varoriginalArr=this6lettempArr=[]7letresultData=[]8for(leti=0;i<originalArr.length;i++)9{10......
  • JavaScript 笔记(二)事件循环机制
    一、事件循环机制1.定义:事件循环是JavaScript中一种重要的异步执行机制。2.作用:管理和协调各种异步任务的执行顺序,保证JavaScript代码的执行顺序和预期一致。3.组成部分:3.1主线程(调用栈):执行任务;3.2任务队列:存放异步任务;3.3事件循环......
  • Java的SPI机制实践
    JavaSPI机制概述先给出结论:“Java的SPI是一种服务发现机制,用于约定接口和动态发现实现类,体现了分层解耦的思想”。Java的SPI机制常用于框架扩展或组件替换,最常见的JavaSPI应用就是JDBCDriver,JDK提供了java.sql.Driver接口,却将具体的实现交给了相应的数据库驱动,比如:在mysql-co......
  • Java高并发编程的关键概念和技术,深入理解并成功应对高并发问题
    Java高并发编程的关键概念和技术,深入理解并成功应对高并发问题1.是什么是高并发?高并发指的是系统在同一时间点需要处理大量并发请求的能力。这些请求可能来自多个用户或者多个线程。在高并发环境下,传统的串行处理方式往往无法满足性能需求,因此需要采用并发编程来提高系统的吞吐......
  • 浅谈 OI 中各种合并操作
    前言合并操作一直是OI中一大考点,今天请各位跟着笔者来梳理一下各种合并操作。启发式合并几乎可以说是最经典的合并了。假定我们可以在\(O(k)\)的时间内往某个集合中插入一个数,那么我们就可以在\(O(n\lognk)\)的时间内合并若干个元素总量为\(n\)的集合。集合启发式......