<返回更多

Java高级特性之集合

2022-08-03    Java开发技术分享
加入收藏

JAVA集合框架

一、Java集合框架概述

 

1、数组与集合的区别:

1) 数组长度不可变化而且无法保存具有映射关系的数据;集合类用于保存数量不确定的数据,以及保存具有映射关系的数据。

2)数组元素既可以是基本类型的值,也可以是对象;集合只能保存对象。

2、Java集合类主要由两个根接口Collection和Map派生出来的,Collection派生出了三个子接口:List、Set、Queue(Java5新增的队列),因此Java集合大致也可分成List(有序、可重复集合、可直接根据元素的索引来访问)、Set(无序、不可重复集合、只能根据元素本身来访问)、Queue(队列集合)、Map(存储key-value对的集合,可根据元素的key来访问value)这四种。

二、Java集合常见接口及实现类

1、Collection接口常见方法

 

2、 List集合

实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。

它们都可以容纳所有类型的对象,包括 null,允许重复,并且都保证元素的存储顺序。 ( 可重复,有顺序)

1)ArrayList

ArrayList 对数组进行了封装,实现了长度可变的数组(动态数组),和数组采用相同存储方式,在内存中分配连续的空间,它的优点在于遍历元素和随即访问元素的效率比较高。

ArrayList特点:线程不安全,查询速度快 ; 底层数据结构是数组结构 ; 扩容增量:原容量的 1.5倍 , 如 ArrayList的容量为10,一次扩容后是容量为15 。

2)LinkedList

LinkedList是List接口的另一个实现,除了可以根据索引访问集合元素外,LinkedList还实现了Deque接口,可以当作双端队列来使用,也就是说,既可以当作“栈”使用,又可以当作队列使用。

LinkedList 采用链表存储方式,优点在于插入、删除元素时效率比较高,它提供了额外的 addFirst()、addLast()、removeFirst()和 removeLast()等方法,可以在LinkedList 的首部或尾部进行插入或者删除操作。

3)Vector

与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。

3、 Set集合

实现Set集合的接口主要有:HashSet、TreeSet、LinkedHashSet;

Set集合与Collection的方法相同,由于Set集合不允许存储相同的元素,所以如果把两个相同元素添加到同一个Set集合,则添加操作失败,新元素不会被加入,add()方法返回false。(无序、不重复)

1)HashSet

HashSet是按照hash算法来存储元素的,因此具有很好的存取和查找性能。

HashSet存储原理如下:

当向HashSet集合存储一个元素时,HashSet会调用该对象的hashCode()方法得到其hashCode值,然后根据hashCode值决定该对象的存储位置。HashSet集合判断两个元素相等的标准是(1)两个对象通过equals()方法比较返回true;(2)两个对象的hashCode()方法返回值相等。因此,如果(1)和(2)有一个不满足条件,则认为这两个对象不相等,可以添加成功。如果两个对象的hashCode()方法返回值相等,但是两个对象通过equals()方法比较返回false,HashSet会以链式结构将两个对象保存在同一位置,这将导致性能下降,因此在编码时应避免出现这种情况。

HashSet查找原理如下:

基于HashSet以上的存储原理,在查找元素时,HashSet先计算元素的HashCode值(也就是调用对象的hashCode方法的返回值),然后直接到hashCode值对应的位置去取出元素即可,这就是HashSet速度很快的原因。

HashSet特点:

不能保证元素的顺序;集合元素值可以是null;线程不安全,存取速度快; 底层实现是一个 HashMap(保存数据),实现Set接口; 默认初始容量为 16; 加载因子为 0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容; 扩容增量:原容量的 1 倍; 如 HashSet的容量为16,一次扩容后是容量为32。

2)LinkedHashSet

LinkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的hashCode值来决定元素的存储位置。但它使用链表维护元素的次序,元素的顺序与添加顺序一致。由于LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet,但在迭代访问Set里的全部元素时由很好的性能。

3)TreeSet

TreeSet可以保证元素处于排序状态,它采用红黑树的数据结构来存储集合元素。TreeSet支持两种排序方法:自然排序和定制排序,默认采用自然排序。

♦ 自然排序

TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素的大小关系,然后将元素按照升序排列,这就是自然排序。如果试图将一个对象添加到TreeSet集合中,则该对象必须实现Comparable接口,否则会抛出异常。当一个对象调用方法与另一个对象比较时,例如obj1.compareTo(obj2),如果该方法返回0,则两个对象相等;如果返回一个正数,则obj1大于obj2;如果返回一个负数,则obj1小于obj2。

♦ 定制排序

想要实现定制排序,需要在创建TreeSet集合对象时,提供一个Comparator对象与该TreeSet集合关联,由Comparator对象负责集合元素的排序逻辑。

综上:自然排序实现的是Comparable接口,定制排序实现的是Comparator接口。

4、Map集合

Map接口采用键值对Map<K,V>的存储方式,保存具有映射关系的数据,因此,Map集合里保存两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value,key和value可以是任意引用类型的数据。key值不允许重复,可以为null。如果添加key-value对时Map中已经有重复的key,则新添加的value会覆盖该key原来对应的value。

常用实现类主要有HashMap、LinkedHashMap、TreeMap。

1)HashMap

对于 HashMap而言,key是唯一的,不可以重复的 。 所以,以相同的 key 把不同的value插入到 Map中会导致旧元素被覆盖,只留下最后插入的元素 。 不过,同一个对象可以作为值插入到 map中,只要对应的key不一样 。

HashMap由 数组 +链表 组成的 ,数组是 HashMap的主体,链表则是主要为了解决哈希冲突而存在的 。

HashMap工作原理如下:

HashMap基于hashing原理,通过put()和get()方法存储和获取对象。当我们将键值对传递给put()方法时,它调用建对象的hashCode()方法来计算hashCode值,然后找到bucket位置来储存值对象。当获取对象时,通过建对象的equals()方法找到正确的键值对,然后返回对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会存储在链表的下一个节点中。

HashMap特点:

  • Map提供了一种映射关系,元素是以键值对(key-value)的形式存储的,能根据key快速查找value;
  • Map 中的键值对以 Entry 类型的对象实例形式存在;
  • key 值不能重复, value 值可以重复;
  • key 对 value 是多(一)对一的关系;
  • Map 接口提供了返回 key 值集合、 value 值集合、 Entry 值集合,的方法;
  • Map 支持泛型,形式如: Map<K,V>;
  • 默认初始容量为 16 ;
  • 加载因子为 0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容 ;
  • 扩容增量:原容量的 1 倍。

2)LinkedHashMap

LinkedHashMap使用双向链表来维护key-value对的次序(其实只需要考虑key的次序即可),该链表负责维护Map的迭代顺序,与插入顺序一致,因此性能比HashMap低,但在迭代访问Map里的全部元素时有较好的性能。

大多数情况下,只要不涉及线程安全问题, Map基本都可以使用HashMap,不过HashMap有一个问题,是 迭代 HashMap的顺序并不是HashMap放置的顺序 , 也就是无序。 HashMap的这一缺点往往会带来困扰,因为有些场景,我们期待一个有序的Map。这个时候,LinkedHashMap就闪亮登场了,它虽然增加了时间和空间上的开销,但是 通过维护一个运行于所有条目的双向链表, LinkedHashMap保证了元素迭代的顺序 。 该迭代顺序可以是插入顺序或者是访问顺序。

LinkedHashMap可以认为是 HashMap+LinkedList , 即它既使用 HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序。

LinkedHashMap的基本实现思想就是---- 多态 

3)TreeMap

TreeMap是SortedMap的实现类,是一个红黑树的数据结构,每个key-value对作为红黑树的一个节点。TreeMap存储key-value对时,需要根据key对节点进行排序。TreeMap也有两种排序方式:

♦ 自然排序:TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则会抛出ClassCastException。

♦ 定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。

TreeMap特点:

· TreeMap是非线程安全的;

·TreeMap是用键来进行升序顺序来排序的。通过Comparable 或 Comparator来排序;

· 和 HashMap一样,如果插入重复的元素,后面的元素会覆盖前面的 ;

· 键不可以为 null(如果比较器对null做了处理,就可以为null),但是值可以为null。

5、遍历

第一种: for循环遍历

1 for (int i = 0; i < heros.size(); i++) {2             Hero h = heros.get(i);3             System.out.println(h);4         }

第二种:迭代器遍历

 1 System.out.println("--------使用while的iterator-------"); 2         Iterator<Hero> it= heros.iterator(); 3         //从最开始的位置判断"下一个"位置是否有数据 4         //如果有就通过next取出来,并且把指针向下移动 5         //直到"下一个"位置没有数据 6         while(it.hasNext()){ 7             Hero h = it.next(); 8             System.out.println(h); 9         }10         //迭代器的for写法11         System.out.println("--------使用for的iterator-------");12         for (Iterator<Hero> iterator = heros.iterator(); iterator.hasNext();) {13             Hero hero = (Hero) iterator.next();14             System.out.println(hero);15         }

第三种:增强 for循环

1 System.out.println("--------增强型for循环-------");2         for (Hero h : heros) {3             System.out.println(h);4         }
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>