Java集合-Java集合基础

这篇具有很好参考价值的文章主要介绍了Java集合-Java集合基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

讲一讲Java集合吧

集合的使用

为什么要使用集合?

如何选用集合?

Collection

Collection与Collections的区别是什么?

Collections.sort和Arrays.sort的实现原理

为何Collection不从Cloneable和Serializable接口继承?

线程安全集合类

哪些集合类是线程安全的?哪些不安全?

怎么确保一个集合不能被修改?

iterator

迭代器 Iterator 是什么?怎么用,有什么特点?

Iterator 和 ListIterator 有什么区别?

Enumeration和Iterator接口的区别?

快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?


讲一讲Java集合吧

Java集合-Java集合基础

所有集合类都位于Java.util包下,Java的集合类主要由两个接口派生而出 : Collection和Map, Collection和Map是Java集合框架的根接口,两个接口又包含了子接口和实现类

对于Collection接口,下面又有三个主要的子接口 : List,Set,Queue

List主要实现类 :

  • ArrayList: 底层是Object[] 数组
  • LinkedList: 底层是 双向链表(JDK1.6 之前为循环链表,JDK1.7 取消了循环)
  • Vector:底层是Object[] 数组
  • Stack : 继承自Vector

Set主要实现类 :

  • HashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素
  • LinkedHashSet: LinkedHashSet 是 HashSet 的子类,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的 LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别的
  • TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树

Queue接口主要实现类 :

  • PriorityQueue: Object[] 数组来实现二叉堆--->完全二叉树
  • ArrayQueue: Object[] 数组 + 双指针

对于Map接口,下面又有主要的实现类有 :HashMap,LinkedHashMap,HashTable,TreeMap

  • HashMap: JDK1.8 之前 HashMap 由数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间
  • LinkedHashMap: LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
  • Hashtable: 数组+链表组成的,数组是 Hashtable 的主体,链表则是主要为了解决哈希冲突而存在的
  • TreeMap: 底层是由红黑树实现的,保证有序

List,Set,Queue,Map接口的特点

  • List: 存储的元素是有序的、可重复的。
  • Set: 存储的元素是无序的、不可重复的。
  • Queue: 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。
  • Map: 用于存储键值对(key-val形式)的元素, 根据key获取val,key是无序的,不可重复,val是无序的,可重复

集合的使用

为什么要使用集合?

先说一下使用数组的缺点 :

  1. 一旦初始化以后,其长度就不可修改.
  2. 数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
  3. 数组只能存放一组类型相同的元素,单一.实际开发中存储的数据类型可能是多种多样的
  4. 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
  5. 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
  6. 数组不能存放键值对

为啥使用集合 ?

集合提高了数据存储的灵活性,Java 集合不仅可以用来存储不同类型不同数量的对象,还可以保存具有映射关系的数据,还可以提供相应的方法来提高操作容器的效率

如何选用集合?

主要是根据集合的特点来进行选择

  • 如果你想要存放键值对,根据key获取到val,那么就可以选用Map接口下的集合
    • 需要排序,选择TreeMap
    • 不需要排序就选择HashMap
    • 想要保证线程安全就选用ConcurrentHashMap
  • 否则就是指需要存储单个元素,那么可以选用Collection接口下的集合
    • 需要保证元素唯一,需要排序选择TreeSet , 否则可以选择HashSet
    • 需要按照某种排队规则可以选用Queue接口下的集合如PriorityQueue,ArrayDeque
    • 只需存放单一元素,有序,可重复 就可以选择List接口下的集合,如果需要保证线程安全,可以使用vector,SynchronizedList(使用Collections.synchronizedList(list); 将list包装成SynchronizedList),copyOnWriteList, 否则可以选择比如 ArrayList,LinkedList ,增删多:linkedList,查询多 : ArrayList

Collection

Collection与Collections的区别是什么?

collection 是一个接口 主要的接口如 List, Set, Queue,这三个主要的接口有实现类来帮助我们操作元素.

collections是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序(sort)、搜索、反转(reverse)、拷贝(copy)以及线程安全等各种操作

Collections 工具类常用方法:

  • 排序
void reverse(List list)//反转
void shuffle(List list)//随机排序
void sort(List list)//按自然排序的升序排序
void sort(List list, Comparator c)//定制排序,由Comparator控制排序逻辑
void swap(List list, int i , int j)//交换两个索引位置的元素
void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面
  • 查找,替换操作
int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll)//根据元素的自然顺序,返回最大的元素。 类比int min(Collection coll)
int max(Collection coll, Comparator c)//根据定制排序,返回最大元素,排序规则由Comparatator类控制。类比int min(Collection coll, Comparator c)
void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素
int frequency(Collection c, Object o)//统计元素出现次数
int indexOfSubList(List list, List target)//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target)
boolean replaceAll(List list, Object oldVal, Object newVal)//用新元素替换旧元素
  • 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合)

Collections 提供了多个synchronizedXxx()方法·,该方法可以将指定集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题。

我们知道 HashSet,TreeSet,ArrayList,LinkedList,HashMap,TreeMap 都是线程不安全的。Collections 提供了多个静态方法可以把他们包装成线程同步的集合。

synchronizedCollection(Collection<T>  c) //返回指定 collection 支持的同步(线程安全的)collection。
synchronizedList(List<T> list)//返回指定列表支持的同步(线程安全的)List。
synchronizedMap(Map<K,V> m) //返回由指定映射支持的同步(线程安全的)Map。
synchronizedSet(Set<T> s) //返回指定 set 支持的同步(线程安全的)set。

Collections.sort和Arrays.sort的实现原理

为何Collection不从Cloneable和Serializable接口继承?

Collection是集合的根接口,可以存储一组对象,因为对象的存储多种多样.所以如何存储对象是由接口的具体实现来决定的,比如,比如 list允许重复而set不允许重复, 对于克隆和序列化而言,只对具体的实体和对象才有意义,不能把一个接口,抽象类克隆,序列化甚至反序列化. 所以具体的Collection实现类 是否可以克隆,序列化由其自身来决定,不能由超类强行赋予.

举一个反例吧 : 如果Collection继承了clone和serializable,那么它的所有实现类都会实现这两个接口,但是如果某个实现类不需要被克隆,甚至不允许序列化,那么就与collection矛盾了

线程安全集合类

哪些集合类是线程安全的?哪些不安全?

  1. String
  2. Integer
  3. StringBuffer
  4. Random
  5. Vector
  6. Hashtable
  7. java.util.concurrent 包下的类

剩下的不是线程安全的

怎么确保一个集合不能被修改?

iterator

迭代器 Iterator 是什么?怎么用,有什么特点?

Iterator 和 ListIterator 有什么区别?

  • Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。
  • Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历).(ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以)
  • ListIterator有add()方法,可以向List中添加对象,而Iterator不可以;
  • ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能;
  • 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现,Iterator仅能遍历,不能修改。

Enumeration和Iterator接口的区别?

快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?

fail-fast 和fail-safe 是在不允许在遍历集合的时候去修改的两种应对措施,因为在遍历的时候可能会有其他线程来修改,这时fail-fast是立刻抛出异常,而fail-safe则是会有应对策略,比如牺牲一致性来保证整个遍历的运行完成

  • ArrayList是fail-fast的典型代表,当在遍历的时候有其他线程修改,则立刻抛出异常ConcurrentModificationException (遍历的同时不能修改)
    • 原理 : 迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历.
  • copyOnWirteArrayList是fail-safe的典型代表, 当在遍历的时候有其他线程修改 , 会有应对策略,比如牺牲一致性让整个遍历运行完成 (遍历的同时可以修改)
    • 原理 : fail-safe集合中的所有对集合的修改都是先复制一份副本,然后在副本集合中进行修改,并不是直接对原集合进行修改

参考:

博客园 一些博客

csdn一些博客

https://www.cnblogs.com/williamjie/p/11158588.html

Javaguide : Java集合常见面试题总结(下) | JavaGuide(Java面试+学习指南)文章来源地址https://www.toymoban.com/news/detail-436496.html

到了这里,关于Java集合-Java集合基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较已经为什么禁止使用double直接构造BigDecimal

    阿里Java开发手册嵩山版中明确指出: 1、BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法 equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度 2、禁止使用构造方法BigDecimal(double)的方式把double值转换为BigDecimal对象 BigDecimal(double)存在精度损

    2024年02月07日
    浏览(56)
  • git将文件或目录添加进了.gitignore文件,为什么不生效?

    如题,之所以将文件添加进了.gitignore文件但不生效,是因为该文件已经被add进git仓库了,已经被git托管了,这时git就没法ignore了。解决办法是先用git rm --cached将这些文件从git仓库中取消托管并提交,然后.gitignore文件才会生效。详细见如下描述。 已经添加到git仓库中的文件,

    2024年02月03日
    浏览(52)
  • Java面试题:为什么HashMap不建议使用对象作为Key?

    HashMap 是一种基于哈希表的动态数据结构,它允许使用任意不可变对象作为键(key)来存储和检索数据。然而,在某些情况下,使用对象作为 HashMap 的键可能会遇到一些问题。   首先,我们需要明确对象作为 HashMap 的键需要满足一些条件: 不可变性:对象的属性不能被修改,

    2024年04月22日
    浏览(55)
  • 【Day1】零基础学java--》记事本运行java程序,通熟语言让你彻底明白为什么配置java环境变量

    前言: 大家好,我是 良辰丫 ,从今天开始我将协同大家一起从零基础学习Java,期待与君为伴,走向海的彼岸。💕💕💕 🧑个人主页:良辰针不戳 📖所属专栏:EveryDay零基础学java 🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。 💦期

    2024年02月11日
    浏览(45)
  • C#: Json序列化和反序列化,集合为什么多出来一些元素?

    如下面的例子,很容易看出问题: 如果类本身的无参构造函数, 就添加了一些元素,序列化,再反序列化,会导致元素增加。 如果要避免,必须添加: new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace }

    2024年02月10日
    浏览(56)
  • 为什么pycharm远程连接服务器运行时总会出现找不到文件或目录

    目录 解决方法 为什么会出现这样的问题 我们需要修改一个设置 具体步骤如下: 1、右下角点击它,选择interpreter setting  2、进入下图界面,点击箭头所指位置,选择show all 3、进入下图界面,选择你要修改的python interpreter,点哪个🖊进行修改    4、进入下图界面,默认情况下

    2024年02月15日
    浏览(70)
  • 什么是 Java 中的数据库连接池?为什么使用连接池来管理数据库连接?

    数据库连接池(database connection pool)是在 Java 中用于管理数据库连接的一种技术。它的主要目的是提高数据库连接的重用性和性能。在传统的数据库连接方式中,每次与数据库建立连接时都需要进行一系列的网络通信和身份验证操作,这样的开销较大并且会影响应用程序的性

    2024年02月06日
    浏览(63)
  • Oracle21C:Windows版本的安装、卸载、环境变量配置、避坑指南|ORA-12514|为什么安装目录没有bin目录

    安装Oracle21C(点击下载),因不得其法,各种报错,导致不能正常使用Oracle。  提示:版本是Oracle21C, 其他版本可能存在差异, 目前官网已更新到Oracle23C (进官网后,向下滚动,可下载其他版本)。  1)Oracle下载地址:官网下载页面 2)navecat下载地址:navecate 3)sqlplus下载地

    2024年01月25日
    浏览(56)
  • 在Java中使用FileReader.read()进行读取文件时,为什么乱码?两个方法解决

     以上代码是有可能出现代码输出混乱的情况的,输出效果如下: 可能会出现乱码的问题: 原因可能是文件编码与程序读取时使用的编码不一致。在创建 FileReader 对象时,没有指定文件的编码格式,因此默认使用的是系统默认的编码格式。如果文件中包含非系统默认编码格式

    2024年02月03日
    浏览(44)
  • Java开发手册中为什么不建议在for循环中使用“+“进行字符串操作

    java开发手册中对于循环体中进行字符串的拼接要求如下: 【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。 说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append操作, 最后通过 toString 方法返回

    2024年02月08日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包