JAVA常见容器_JAVA比较容器

JAVA常见容器_JAVA比较容器假设上面已经有了各个容器的继承关系,我们就顺着继承关系说一下各个接口或者类的特点吧。Iterable接口Iterable是一个超级接口,被Collection所继承。它只有一个方法:Iterator<T>iterator()//即返回一个迭代器迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

本文主要介绍JAVA中常见容器间的关系和主要区别。JAVA中的容器种类很多,且各有特点。为此特意进行学习研究,写下此文,作为一点总结。若有错误,欢迎拍砖。
JAVA各容器继承关系

上图是JAVA常见的各个容器的继承关系,我们就顺着继承关系说一下各个接口或者类的特点吧。


Iterable 接口

  • Iterable是一个超级接口,被Collection所继承。它只有一个方法: Iterator<T> iterator() //即返回一个迭代器

  • 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为**“轻量级”**对象,因为创建它的代价小。

  • Java中的Iterator功能比较简单,并且只能单向移动
      (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
      (2) 使用next()获得序列中的下一个元素。
      (3) 使用hasNext()检查序列中是否还有元素。
      (4) 使用remove()将迭代器新返回的元素删除。

  • Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
      举一个例子来说明迭代器的用法:

public static void main(String args[]) {
		List<String> l = new ArrayList<String>();
		l.add("aa");
		l.add("bb");
		l.add("cc");
		Iterator iter = l.iterator();
		while(iter.hasNext()){
			System.out.println((String)iter.next());
		}
//	for循环的版本
//		for(Iterator<String> iter=l.iterator();iter.hasNext();){
//			String str = (String)iter.next();
//			System.out.println(str);
//		}  			
	}

Jetbrains全家桶1年46,售后保障稳定

运行结果:
运行结果

很明显,iterator用于while循环更方便简洁一些。


Collection 接口

我们直接打开API文档进行查看
Collection接口 文档中写道,JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。也就是一般不会直接使用Collection,而是会使用它的子类,如List或Set。

在图中我标注了4点,不同的Collection子类对于有序性、重复性、null、线程同步都有不同的策略。基于此,Collection的介绍就这样,下面就其具体的子类来进行介绍。



List 接口

  • List是有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

  • 用户插入的顺序或者指定的位置就是元素插入的位置。它与Set不同,List允许插入重复的值

  • List 接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入替换,以及双向访问。还提供了一个方法(如下)来获取从列表中指定位置开始的列表迭代器。

ListIterator <E> listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始

  • List 接口提供了两种搜索指定对象的方法。从性能的观点来看,应该小心使用这些方法。在很多实现中,它们将执行高开销的线性搜索。

  • List 接口提供了两种在列表的任意位置高效插入和移除多个元素的方法。

  • List的子类

    • List最流行的实现类有Vector、ArrayList、LinkedList。三者的区别将在下文提及。
    • 1.1) ArrayList (类)
    1. ArrayLis是基于数组实现的List类,它封装了一个动态的、增长的、允许再分配的Object[ ]数组.它允许对元素进行快速随机访问
    2. 当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
    • 1.2)Vector (类)
    1. Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList。所以现在已经不太常用了
      1.2.1)Stack (类)

      Stack是Vector提供的一个子类,用于模拟”栈”这种数据结构(LIFO后进先出)

    • 1.3)LinkedList (类)
    1. LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。
    2. 另外,它还实现了Deque接口,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

    关于ArrayList和Vector的区别,再次回顾一下:

    名称 扩容方式(默认) 线程安全 速度 有效个数的属性
    ArrayList 增长50% 线程不安全 size
    Vector 增长一倍 线程安全 elementCount
    共同点 如果新增的有效元素个数超过数组本身的长度,都会导致数组进行扩容 remove,add(index,obj)方法都会导致内部数组进行数据拷贝的操作,这样在大数据量时,可能会影响效率

写在后面:List接口的排序可以通过Collections.sort()来进行定制排序
只需要继承Comparable接口后,重写compareTo()**方法
代码如下:

	public class Student extends Thread implements Comparable {	
   private int age;
   private String name;
   private String tel;
   private int height;

   public Student( String name,int age, String tel, int height) {
   	this.age = age;
   	this.name = name;
   	this.tel = tel;
   	this.height = height;
   }

   public static void main(String args[]) throws InterruptedException{
   	Student stu1 = new Student("张三",21,"156482",172);
   	Student stu2 = new Student("李四",18,"561618",168);
   	Student stu3 = new Student("王五",19,"841681",170);
   	Student stu4 = new Student("赵七",20,"562595",180);
   	
   	List<Student> list = new ArrayList<Student>();
   	//乱序插入
   	list.add(stu3);
   	list.add(stu1);
   	list.add(stu4);
   	list.add(stu2);
   	
   	System.out.println("-----------排序前----------");
   	Iterator<Student> it = list.iterator();
   	while(it.hasNext()){
   		System.out.println(it.next());
   	}
   	/*
   	 * 使用Collections的sort方法让集合排序,使用其方法必须要重写
   	 * Comparable接口的compareTo()方法
   	 * */
   	Collections.sort(list);
   	System.out.println("-----------按照年龄排序后----------");
   	for(int i=0;i<list.size();i++){
   		System.out.println(list.get(i).toString());
   	}
   }

   //重写compareTo方法,用age来比较。也可以用别的来比较
   @Override
   public int compareTo(Object o) {
   	//使用当前对象的年龄和其他对象的年龄比较,如果<0返回负数,>0返回正数,=0返回0
   	int z = this.age - ((Student)o).getAge();
   	if(z<0) 
   		return -1;  // 返回其他负数也行
   	else if(z == 0) 
   		return 0;
   	else 
   		return 1;  //返回其他正数也行
   }
   
   //重写toString,便于输出
   @Override
   public String toString(){
   	return name+","+age+","+tel+","+height;
   }

输出结果如下:
在这里插入图片描述



Set接口

  • Set,顾名思义,集合的意思。java的集合和数学的集合一样,满足集合的无序性,确定性,单一性。所以可以很好的理解,Set是无序、不可重复的。同时,如果有多个null,则不满足单一性了,所以Set只能有一个null。
  • Set类似于一个罐子,丢进Set的元素没有先后的差别
  • Set判断两个对象相同不是使用”==”运算符,而是根据equals方法。也就是说,我们在加入一个新元素的时候,如果这个新元素对象和Set中已有对象进行注意equals比较都返回false,则Set就会接受这个新元素对象,否则拒绝。
    ——因为Set的这个制约,在使用Set集合的时候,应该注意两点:
    1. 为Set集合里的元素的实现类实现一个有效的equals(Object)方法;
    2. 对Set的构造函数,传入的Collection参数不能包含重复的元素。
  • Set的子类

    • Set最流行的实现类有HashSet、TreeSet、LinkedHashSet(从HashSet继承而来)。
    • 1.1) HashSet (类)
    1. HashSet是Set接口的典型实现,HashSet使用HASH算法来存储集合中的元素,因此具有良好的存取和查找性能。当向HashSet集合中存入一个元素时,HashSet会调用该对象的 hashCode()方法来得到该对象的hashCode值,然后根据该HashCode值决定该对象在HashSet中的存储位置。
    2. 值得主要的是,HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法的返回值相等

      1.1.1)LinkedHashSet(类)
      1. LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但和HashSet不同的是,它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。
      2. 当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。
      3. LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时(遍历)将有很好的性能(链表很适合进行遍历)LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时(遍历)将有很好的性能(链表很适合进行遍历)
    • 1.2) SortedSet (接口):

      此接口主要用于排序操作,实现了此接口的子类都属于排序的子类

      • 1.2.1)TreeSet(类)
      • TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态
    • 1.3) EnumSet (类)
    • EnumSet是一个专门为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式、或隐式地指定。EnumSet的集合元素也是有序的,


Queue 接口

此接口用于模拟“队列”数据结构(FIFO)。新插入的元素放在队尾,队头存放着保存时间最长的元素。

  • Queue的子类、子接口

    • 1.1) PriorityQueue—— 优先队列(类)
    • 其实它并没有按照插入的顺序来存放元素,而是按照队列中某个属性的大小来排列的。故而叫优先队列。
    • 1.2) Deque——双端队列(接口)
      • 1.2.1)ArrayDeque(类)

        基于数组的双端队列,类似于ArrayList有一个Object[] 数组。

      • 1.2.2)LinkedList (类)(上文已有,略)

    简单回顾一下上述三个接口的区别

容器名是否有序是否可重复null的个数
List有序可重复允许多个null
Set无序不可重复只允许一个null
Queue有序(FIFO)可重复通常不允许插入null


Map 接口

  • Map不是collection的子接口或者实现类。Map是一个接口。

  • Map用于保存具有“映射关系”的数据。每个Entry都持有键-值两个对象。其中,Value可能重复,但是Key不允许重复(和Set类似)。

  • Map可以有多个Value为null,但是只能有一个Key为null。

  • Map的子类、子接口

  • 1) HashMap (类)

    和HashSet集合不能保证元素的顺序一样,HashMap也不能保证key-value对的顺序。并且类似于HashSet判断两个key是否相等的标准一样: 两个key通过equals()方法比较返回true、 同时两个key的hashCode值也必须相等

    • 1.1) LinkedHashMap (类)
    • LinkedHashMap也使用双向链表来维护key-value对的次序,该链表负责维护Map的迭代顺序,与key-value对的插入顺序一致(注意和TreeMap对所有的key-value进行排序区分)。

  • 2) HashTable (类)

    是一个古老的Map实现类。

    • 2.1) Properties(类)
    • Properties对象在处理属性文件时特别方便(windows平台的.ini文件)。Properties类可以把Map对象和属性文件关联,从而把Map对象的key – value对写入到属性文件中,也可把属性文件中的“属性名-属性值”加载进Map对象中。
  • 3) SortedMap(接口)

    如同Set->SortedSet->TreeSet一样,Map也有Map->SortedMap->TreeMap的继承关系。

    • 3.1) TreeMap(类)
    • TreeMap是一个红黑树结构,每个键值对都作为红黑树的一个节点。TreeMap存储键值对时,需要根据key对节点进行排序,TreeMap可以保证所有的key-value对处于有序状态。 同时,TreeMap也有两种排序方式:自然排序、定制排序(类似于上面List的重写CompareTo()方法)。
  • 4) WeakHashMap(类)
    • 看名字就能发现,这是Weak后的HashMap。但是二者大体差别不大。
    • 区别在于,HashMap的key保留了对实际对象的强引用,这意味着只要该HashMap对象不被销毁,该HashMap所引用的对象就不会被垃圾回收。
    • 但WeakHashMap的key只保留了对实际对象的弱引用,这意味着如果WeakHashMap对象的key所引用的对象没有被其他强引用变量所引用,则这些key所引用的对象可能被垃圾回收,当垃圾回收了该key所对应的实际对象之后,WeakHashMap也可能自动删除这些key所对应的key-value对
  • 5) IdentityHashMap(类)
    • 这个类也和HashMap类似(怎么那么多类似的hhhh),区别在于,在IdentityHashMap中,当且仅当两个key严格相等(key1==key2)时,IdentityHashMap才认为两个key相等
  • 6) EnumMap(类)
    • EnumMap是一个与枚举类一起使用的Map实现,EnumMap中的所有key都必须是单个枚举类的枚举值。创建EnumMap时必须显式或隐式指定它对应的枚举类。EnumMap根据key的自然顺序存储。


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222881.html原文链接:https://javaforall.net

(0)
上一篇 2025年7月3日 下午1:15
下一篇 2025年7月3日 下午1:43


相关推荐

  • java tair,Tair 简介

    java tair,Tair 简介1Tair 的功能 Tair 是一个 Key Value 结构数据的解决方案 它默认支持基于内存和文件的两种存储方式 分别和我们通常所说的缓存和持久化存储对应 Tair 除了普通 Key Value 系统提供的功能 比如 get put delete 以及批量接口外 还有一些附加的实用功能 使得其有更广的适用场景 包括 Version 支持原子计数器 Item 支持 1 1Version 支持 Tair 中的每个数据都包含

    2026年3月19日
    2
  • @RequestParam注解详解

    @RequestParam注解详解@RequestParam是传递参数的.@RequestParam用于将请求参数区数据映射到功能处理方法的参数上。publicStringqueryUserName(@RequestParamStringuserName)在url中输入:localhost:8080/**/?userName=zhangsan请求中包含username参数(如/requestparam1?userName=…

    2025年7月10日
    8
  • 彻底删除2345安全卫士_怎么卸载安全卫士

    彻底删除2345安全卫士_怎么卸载安全卫士以下解决方法需要你有一个U盘PE启动盘。今天帮网友解决一个问题:2345安全卫士服务进程怎么也杀不掉的问题。众所周知,2345因某些原因在网友的心中口碑是非常地差,这不,这两天就有一位网友中招了。要不是担心以后还会中招,折腾了这么久早就重装系统了!!2345安全卫士卸载不了,2345SafeCenterSvc服务更是无法关闭,卸载了又出现,简直像幽灵一样!出现这个情况,说明你在…

    2025年8月29日
    6
  • MAC怎么安装brew

    MAC怎么安装brew用brewinstallgit安装git,然后提示安装失败,百度后发现是需要先安装brew用官网给的命令,报错,太绝人了,百度了好多都无法成功,最后找到一个大佬的解决办法,贴出来**解决**苹果电脑常规安装脚本(推荐完全体几分钟安装完成):/bin/zsh-c”$(curl-fsSLhttps://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)”苹果电脑极速安装脚本(精简版几秒钟安装完成):/bin/zsh-

    2025年7月4日
    6
  • 最小二乘法简明推导过程

    最小二乘法简明推导过程最小二乘法推导最小二乘法公式J(θ)=1m∑i=1m(y(i)−hθ(x(i)))2J(\theta)=\frac1m\sum_{i=1}^m(y^{(i)}-h_{\theta}(x^{(i)}))^2J(θ)=m1​i=1∑m​(y(i)−hθ​(x(i)))2证明1.假设设数据中未被考虑进来的特征和人为无法控制的噪声为ε\varepsilonε。即y(i)=θTx(i)…

    2022年5月13日
    70
  • Pytest(6)重复运行用例pytest-repeat「建议收藏」

    Pytest(6)重复运行用例pytest-repeat「建议收藏」前言平常在做功能测试的时候,经常会遇到某个模块不稳定,偶然会出现一些bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来。自动化运行用例时候,也会出现偶然的bug,可以针对单个用例,

    2022年7月31日
    10

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号