集合:

  ·数组其实就是一个集合;集合实际上就是一个容器;

  ·集合通常在实际开发中,用于查询数据库返回的多条数据,然后存放数据库数据比较多;

  ·集合不能直接存储基本数据类型,也不能存储java对象;

  ·集合中存储的都是java对象中的内存地址(引用);

  ·java中每个不同的集合,底层都对应了不同的数据结构;在集合中存储不同的元素,就相当于在不同的数据结构中存储元素,而且每种数据结构存储元素的方式也不同;

  例如:数组,二叉树、链表、哈希表,等等;

在java中集合分为两大类:

  ·一类是以单个方式存储元素;

    该类的超级父接口是:java.util.collection;

  ·一类以键值对的方式存储元素;

    该类的超级父接口是:java.util.Map;

collection单个方式存储元素:

List集合存储元素的特点:

  ·有序的、可重复的,存储的元素有下标,该处的“有序”不是从大到小排序的意思,而是元素存储进入是这个顺序,取出来也是这个顺序;

set集合存储元素的特点:

  ·无序的、不可重复;该集合中,元素没有下标,元素不可重复,该处的“无序”指的是存元素时是该顺序,但取出来不一定是存进去的顺序;

  ·可以调用sort()方法进行排序,但对List中的元素进行排序,需要保证List集合中的元素实现了Comparable接口;

  List与set集合的特点是相对的;

List下的关系集合:

ArrayList、LinkedList、Vector的区别:

  ·ArrayList底层代码采用了数组的数据结构,该集合是非线程安全的;

  ·LinkedList底层代码采用了双向链表的数据结构;

  ·Vector底层代码采用了数组的数据结构,该集合是线程安全的;但是效率较低;

Set下的关系集合:

  ·HashList 实际上,底层在new的时候,new的是一个HashMap集合,而往HashList中存储元素,本质上就是在向HashMap集合中存储元素,而HashMap集合是一个哈希表数据结构;

  ·sortedSet集合存储元素的特点,因为继承了Set集合,所有它的特点也是无序不可重复的,但是放在sortedSet的元素可以自动排序,可成为有序排序,该集合中的元素自动按照    大小进行顺序排序;

  ·SortSet 接口下有个实现类,这个实现类就是TreeSet;

  ·TreeSet 实际上,底层在new的时候,new的是一个TreeMap集合,而往TreeSet中存储元素,本质上就是在向TreeMap集合中存储元素,TreeMap集合采用了二叉树的数据结构;

Map以键值对的方式存储元素:

  ·Map集合与Collection集合是没有关系的;

  ·Map集合以key和value的方式存储元素;

  ·key和value都是存储java对象的内存地址;

  ·Map下的两个常用实现类,HashMap和Hashtable;

  ·所有Map集合,它的特点都是无序不可重复的;

  ·Map集合的key和set集合存储的特点相同;

HashMap和Hashtable的区别:

  ·HashMap是非线程安全的,底层采用的是哈希表数据结构;

  ·Hashtable是线程安全的,底层采用的是哈希表数据结构;因为线程安全,该集合效率较低;

Properties的特点:

  ·Properties是线程安全的因为继承了Hashtable,另外properties存储元素的时候,也是采用key和value的形式存储,并且key和value只支持String类型的数据,不支持其他类型;

Collection:

  在没有使用“泛型”之前,collection可以存储所有object的子类型,

  使用了“泛型”之后,collection只能存储某个指定的类型;

  :集合中不能存储基本数据类型,也不能存储java对象,只是存储java对象的内存地址;

  Collection中的迭代器,iterator();迭代/遍历;

  迭代器是一个对象;

  Interator();迭代器中的remove()方法,底层会调equals();只要内容一样,即使内存地址不同,也可以删除;但是前提是equals()必须重写;

  集合结构只要发生改变,迭代器必须重新获取;

  而且在迭代的过程中,不能调用集合的remove方法;但是可以调用迭代器的remove方法;

  简单的说,就是集合中的结构发生改变了,迭代器需要重新获取,而且在迭代时,若想要删除元素,必须使用iterator(迭代器)自带的remove方法;

  Collection中的contions和remove方法,底层都会调用equals方法,因此equals方法需要重写;

ArrayList:

·ArrayList初始化的容量为10;(底层先创建了一个长度为0的数组,当添加第一个元素时,初始化容量为10)

  ·ArrayList底层是一个object[]数组;

  ·ArrayList集合的扩容:增长到原容量的1.5倍;

  ·在使用ArrayList集合的底层的数组,数组尽量少扩容,因为效率较低,最后先预估定一个容量值;

  ·ArrayList集合是非线程安全的;

单向链表:

  链表的基本结构是节点(node),对应单向链表来说,任何一个节点node都有两个属性;

  第一个属性:存储的数据;

  第二个属性:下一个节点的内存地址;(节点的内存地址是不连续的)

链表的优点:

  随机增删元素效率较高;(因为增删元素不涉及到大量元素位移)

链表的缺点:

  查询效率较低,每次查找某个元素时,都需要从头节点开始遍历;

双向链表(LinkedList):

  双向链表的基本单元还是节点node,双向链表有三个属性;

  第一个属性:上一个节点的内存地址;

  第二个属性:节点元素;

  第三个属性:下一个节点的内存地址;

  LinkedList集合没有初始化容量;最初链表中没有任何元素,first和last都是null

  LinkedList是一个双向链表;链表对于随机增删来说,效率较高;但查找某个元素效率较低;

  链表中的(节点)元素在空间内存上,内存地址不连续;

Vector:

  Vector底层也是一个数组,初始化容量是10,它是线程安全的;

  Vector扩容后的容量,是原容量的2倍;原容量*2;

  ArrayList集合的扩容容量是:原容量的1.5倍;原容量*1.5;

  如何将一个非线程安全的ArrayList集合转换为一个线程安全的集合:

  使用集合工具类:java.util.collections;

  注意:java.util.collection;是集合接口,

        java.util.collections;是集合工具类,不要搞混了;

  把一个非线程安全的ArrayList集合转换成一个线程安全的,调用collections下的一个方法synchronizedList();即可;

  语法:List myList=new ArrayList();

  引入java.util.collections包;

  Collections.synchronizedList(myList); //这样就可以将一个非线程安全的集合转换成一个线程安全的集合;

泛型机制:

  泛型机制是jdk5.0之后推出的新特性;

  使用泛型后,集合中,只能存储指定的元素类型;

  泛型属性编译阶段的一个新特性,在运行时阶段,没什么用处;

泛型的优点:

  使用泛型之后,集合中,在获取元素时,不需要进行过多的“向下转型”;

泛型的缺点:

  使用泛型之后,集合中存储的元素相对单一,缺乏多样性;

  但是泛型在调用子类特有的方法时,还是需要进行“向下转型”的;

  自动类型推断机制(钻石表达式):

  自动类型推断机制是jdk8之后才有的新特性;

  Jdk8之前:List<User> myList=new ArrayList<User>(); 

  Jdk8之后:List<User> myList=new ArrayList<>(); 

Map集合:

  使用时,需要引用java.util.Map;包

  Map和Collection是没有继承关系的;

  Map的存储数据方式是以key和value的方式存储数据,键值对的方式;

  Key和vakue都是引用数据类型;

  Key和value都是存储对象的内存地址;

  key起到一个主导地位,而value是key的一个附属品;

  Map中有一个Set<Map.Entry<K,Y>> entrySet();方法;

  Map集合通过entrySet()方法转换为这个Set集合,Set集合中,元素的类型是Map.Entry,Map.Entry其实是一个类,一个静态内部类,和String差不多;是Map中的一个内部类;

(HashMap)哈希表数据结构:

   HahsMap底层是一个哈希表/散列表的数据结构;是非线程安全的;

   哈希表是一个数组和单向链表的结合体;它结合了数组与单向链表的优点;

   HashMap实际上,可以理解为是一个一维数组,然后数组中的每一个元素是一个单向链表;

Map.put(k,v)的添加元素实现原理:

   第一步:先将k,y封装到node的对象中;

   第二步:底层会调用hashCode()的方法得出hash值,然后通过哈希函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,则会将node添加到这个位置上,如     果下标对应的位置上有链表,此时会拿着k和链表中所有的k进行equals对比,如果所有对比后的结果是false,那么这个新节点则会添加到链表的末尾,如果有其中一个k返回的结果     是true,  那么就会把原先相同的那个k,把该k中的value值覆盖掉/替换掉;

Map.get(k)的获取元素实现原理:

   先调用k的hashCode()方法得出哈希值,通过哈希算法将哈希值转换成数组下标,然后通过数组下标快速定位到某个位置上,如果这个位置上什么都没有,则会返回null,如果这个     位置上有链表,则会拿着参数k与链表中的所有k,调用equals()方法进行对比,如果equals()方法返回false,那么get()方法也就返回null,如果equals()返回的是true,

   此时就会把返回为true的这个k给到get()方法,而get()方法最终就返回要找的这个value;

   HashMap集合的初始容量是16,默认加载因子是0.75,也就是当集合底层的数组容量达到75%的时候,数组开始扩容;

   注意:HashMap的初始容量必须是2的倍数,这也是官方推荐的,因为可以达到散列分布均匀,为了提高HashMap集合的存取效率,所必须的;扩容后是原容量的2倍;

   在jdk8之后,如果单向链表中元素超过8个,单向链表数据结构会自动变成红黑树数据结构,当红黑树的节点数量小于6时,红黑树数据结构会自动变回单向链表数据结构;

Hashtable集合:

   该集合是线程安全的,但hashtable对线程安全处理效率较低,使用较少;

   Hashtable和HashMap一样,底层都是哈希表数据结构;

   该集合的初始容量是11,默认加载因子是0.75f;扩容后的容量是:原容量*2+1;

Properties集合:

   Properties是一个集合,继承Hashtable,properties的key和value都是String类型;properties被称为属性类对象;

自平衡二叉树:

   自平衡二叉树遵循的是左小右大的原则存放;

   前序遍历:根左右;

   中序遍历:左根右;

   后序遍历:左右根;

注意:中前后说的是“根”的位置;根在前面是前序,根在中间是中序,根在后是后序;

TreeSet/TreeMap集合:

   TreeSet/TreeMap集合采用的是中序遍历方式,Iterator迭代器采用的是中序遍历方式,左根右;

Comparable和Comparator如何选择:

   当比较规则不会发生改变时,或者比较规则只有一个时,建议选择使用Comparable接口;

   如果比较规则有多个,并且多个比较规则频繁切换的时候,建议选择使用Comparator接口;Comparator接口设计符合OCP原则;

Collections工具类:

   Collection和Collections不同;

   Collection是集合接口;

   Collections是集合工具类,方便集合的操作;

Collections中有一个方法,synchronizedList()方法可以将非线程安全的转变成线程安全;

posted on   Jron*  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧



点击右上角即可分享
微信分享提示