Java集合详解

一、List接口

   有序、不唯一

 1、常用方法:

    ① add(): 在列表的最后添加元素;

    ② add(index,obj): 在列表的指定位置插入元素;

    ③ size(): 返回当前列表的元素个数;

    ④ get(int index): 返回下标为index的元素;

     如果没有泛型约束,返回object类型,需要强转;如果有泛型约束,直接返回泛型类型,无需强转

    ⑤ clear(): 清除列表中所有元素。

      isEmpty(): 如果此列表不包含元素,则返回 true。 检测列表是否为空。

    ⑥ contains(): 传入一个对象,检测列表中是否包含该对象;

     如果传入的是String 和 基本数据类型,可以直接比对;

     如果传入的是实体对象,则默认只对比两个对象的地址。因此,需要在实体类重写equal()方法。

    ⑦ indexof(): 传入一个对象,返回该对象在列表中首次出现的地址。

      LastIndexof(): 最后一次。

       ⑧ remove(): 传入一个下标,或者一个对象,删除指定元素。

     如果传入下标,返回被删除的元素对象。如果下标大于size(),会报下标越界异常。

     如果传入对象,则要求重写equal()方法,返回true或false表示删除是否成功。

       ⑨ set(index,object): 用新传入的对象,将指定位置的元素替换掉。

     返回被替换掉的元素对象。

      ⑩ List.subList(1,3): 截取一个子列表,返回List类型。

     toArray(): 将列表转为数组,返回一个object[]类型的数组。

 

 2、实现类:

  1)ArrayList

    实现了一个长度可变的数组,在内存空间中开辟一串连续的空间,与数组的区别在于长度可以随意修改。

       这种存储结构,在循环遍历和随机访问元素时的速度比较快。

  2)LinkedList

    使用链表结构存储数据,在插入和删除元素时速度非常快。

    线程不安全,速度较快,常用!

 

  LinkedList 的特有方法:

    ① add.first(): 开头插入元素。(在该列表开头插入指定的元素。)

     add.last(): 结尾插入元素。(将指定的元素追加到此列表的末尾。)

    ② removeFirst(): 删除第一个元素,并返回被删除的元素。

     removeLast(): 删除最后一个元素,并返回被删除的元素。

    ③ getFirst(): 返回列表的第一个元素,并不会被删除。

     getLast(): 返回列表的最后一个元素,并不会被删除。

 

  3、List循环遍历方法:

  1)使用for循环遍历列表:

    美洲杯赌球 1

  2)使用foreach遍历列表:

    美洲杯赌球 2

  3)使用iterator迭代器遍历列表

    ① 使用列表调用 .iterator()返回一个迭代器对象。

    ② 使用迭代器对象调用.hasNext()判断是否有下一条数据。

    ③ 使用迭代器对象调用.next()取出下一条数据

    美洲杯赌球 3

 

 二、Set接口

  无序、唯一

 1、常用方法: 

  与List接口基本相同。(参考上述List接口常用方法 ↑↑↑)

  但是,由于Set接口中的元素是无序的,因此没有与下标相关的方法

  例如:get(index)  remove(index)  add(index,obj) ... ...

 

 2、实现类  

  1)HashSet

    HashSet 底层是调用HashMap的相关方法,传入数据后,根据数据的hashCode进行散列运算。

    得到一个散列值后再进行运算,确定元素在序列中存储的位置。

 

    HashSet如何确定两个对象是否相等?(存储无序、唯一的数据)

      ① 先判断对象的hashCode(),如果hashCode不同,那肯定不是一个对象;

         如果hashCode相同,那继续判断equal方法。

      ② 重写equal()方法。

      >>>所以,使用HashSet存储实体对象时,必须重写hashCode()和equal()两个方法!

  2)LinkedHashSet

      LinkedHashSet:在HashSet的基础上,新建了一个链表。

      用链表来记录HashSet中元素放入的顺序,因此使用迭代器遍历时,可以按照放入的顺序依次读出元素

美洲杯赌球,    美洲杯赌球 4

  3)TreeSet

    TreeSet:将存入的元素,进行排序,然后再输出。(二叉树原理)  

    如果存入的是实体对象:

    (1)那么实体类必须实现Comparable接口,并重写compareTo()方法

      Set<Person> set3 = new TreeSet<Person>();

      排序后,遍历输出:

      美洲杯赌球 5   

      实现Comparable接口:

      美洲杯赌球 6

       重写compareTo()方法:

      美洲杯赌球 7

  

    (2)或者,也可以在实例化TreeSet的同时,通过构造函数传入一个比较器;     

       比较器:一个实现了Comparator接口,并重写了compare()方法的实现类的对象。

       ① 使用匿名内部类,拿到一个比较器对象。

          Set<Person> set = new TreeSet<Person>(new Comparator(){

           public int compare(Person p1,Person p2){

             return p1.getId() - p2.getId();

            }

          });

        美洲杯赌球 8

 

       ② 自定义一个比较类,实现Comparator 接口。

        Set<Person> set = new TreeSet<Person>(new Compare());

        class Compare implements Comparator(){

          // 重写compare方法。

        }

        美洲杯赌球 9

 

    [ Comparable接口 和 Comparator接口 的区别 ]

    ① Comparable 由实体类实现,重写compareTo()方法;

      实体类实现Comparable接口以后,TreeSet使用空参构造即可。

    ② Comparator 需要单独一个比较类进行实现,重写compare()方法。

      实例化TreeSet的时候,需要传入这个比较类的对象。

队列:先进先出的数据结构。

Java集合框架的组成

美洲杯赌球 10

 

  注意:四个接口的区别

          ① Collection:存储无序的、不唯一的数据;

          ② List:存储有序的、不唯一的数据;

          ③ Set:存储无序的、唯一的数据;

          ④ Map:以键值对的形式存储数据,以键取值,键不可以重复、值可以重复

  下面分别看一下各个接口和对应的实现类:

            美洲杯赌球 11

Collection和Map,是集合框架的根接口。

 三、Map接口   

   以键值对的形式存储数据,以键取值;键不能重复,值可以重复。

  1、常用方法: 

     ① put(key,value): 向map的最后追加一个键值对;

     ② get(key): 通过键,取到一个值;

     ③ clear(): 清除map中的所有数据;

     ④ containsValue(obj): 检测是否包含指定的值;

       containsKey(obj): 检测是否包含指定的键。

     ⑤ replace(key,oid v,new v): 替换值

 

 2、实现类:

   1)HashMapHashTable

     区别:

         ① HashTable 是线程安全(线程同步)的,HashMap是线程不安全的(线程不同步);

      ② HashTable 的键不能为nullHashMap的键可以为null

 

   2)LinkedHashMap

     可以使用链表,记录数据放入的次序,读出的顺序和放入的顺序一致,与LinkedHashSet一样。

   3)TreeMap

      根据键的顺序,进行排序后,输出。(与TreeSet类似,参见上述TreeSet)

     如果传入的是实体对象,必须重写比较函数。(见TreeSet)

 

  3、遍历Map的方式:

  美洲杯赌球 12

   美洲杯赌球 13

 

 

 

 

 

美洲杯赌球 14

HashSet 的后台有一个HashMap;初始化后台容量;只不过生成一个HashSet的话,系统只提供key的访问; 如果有两个Key重复,那么会覆盖之前的;

美洲杯赌球 15

注意:使用栈的时候一定不能提供方法让不是最后一个元素的元素获得出栈的机会。

Vector

ArrayList自动扩充机制
实现机制:ArrayList.ensureCapacity(int minCapacity)
首先得到当前elementData 属性的长度oldCapacity。
然后通过判断oldCapacity和minCapacity参数谁大来决定是否需要扩容, 如果minCapacity大于 
oldCapacity,那么我们就对当前的List对象进行扩容。
扩容的的策略为:取(oldCapacity * 3)/2 1和minCapacity之间更大的那个。然后使用数组拷 
贝的方法,把以前存放的数据转移到新的数组对象中
如果minCapacity不大于oldCapacity那么就不进行扩容。

 

LinkedList

EnumSet特征

EnumSet顾名思义就是专为枚举类型设计的集合,因此集合元素必须是枚举类型,否则会抛出异常。 EnumSet集合也是有序的,其顺序就是Enum类内元素定义的顺序。EnumSet存取的速度非常快,批量操作的速度也很快。EnumSet主要提供以下方法,allOf, complementOf, copyOf, noneOf, of, range等。注意到EnumSet并没有提供任何构造函数,要创建一个EnumSet集合对象,只需要调用allOf等方法,下面是一个EnumSet的例子。

美洲杯赌球 16

执行结果

美洲杯赌球 17

几种Set的比较:
HashSet外部无序地遍历成员。 
成员可为任意Object子类的对象,但如果覆盖了equals方法,同
时注意修改hashCode方法。 
TreeSet外部有序地遍历成员; 
附加实现了SortedSet, 支持子集等要求顺序的操作 
成员要求实现Comparable接口,或者使用Comparator构造
TreeSet。成员一般为同一类型。 
LinkedHashSet外部按成员的插入顺序遍历成员 
成员与HashSet成员类似 
HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。

HashSet的元素存放顺序和我们添加进去时候的顺序没有任何关系,而LinkedHashSet 则保持元素的添加顺序。TreeSet则是对我们的Set中的元素进行排序存放。

一般来说,当您要从集合中以有序的方式抽取元素时,TreeSet 实现就会有用处。为了能顺利进行,添加到 TreeSet 的元素必须是可排序的。 而您同样需要对添加到TreeSet中的类对象实现 Comparable 接口的支持。一般说来,先把元素添加到 HashSet,再把集合转换为 TreeSet 来进行有序遍历会更快。

 

队列和堆栈。

用LinkedList实现栈:
栈(Stack)也是一种特殊的线性表,是一种后进先出(LIFO)的结构。
栈是限定仅在表尾进行插入和删除运算的线性表,表尾称为栈顶(top),表头称为栈底(bottom)。
栈的物理存储可以用顺序存储结构,也可以用链式存储结构。

(与ArrayList相似,区别是Vector是重量级的组件,使用使消耗的资源比较多。)

 

Collection的子接口:

结论:在考虑并发的情况下用Vector(保证线程的安全)。

List常用方法:
void add(int index, Object element) :添加对象element到位置index上
boolean addAll(int index, Collection collection) :在index位置后添加容器collection中所有的元素
Object get(int index) :取出下标为index的位置的元素
int indexOf(Object element) :查找对象element 在List中第一次出现的位置
int lastIndexOf(Object element) :查找对象element 在List中最后出现的位置
Object remove(int index) :删除index位置上的元素 
ListIterator listIterator(int startIndex) :返回一个ListIterator 跌代器,开始位置为startIndex 
List subList(int fromIndex, int toIndex) :返回一个子列表List ,元素存放为从 fromIndex 到toIndex之前的一个元素

数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺点,比数组更灵活更实用,而且不同的集合框架类可适用不同场合。如下:
1:数组能存放基本数据类型和对象,而集合类存放的都是对象的引用,而非对象本身!
2:数组容易固定无法动态改变,集合类容量动态改变。 
3:数组无法判断其中实际存有多少元素,length只告诉了数组的容量,而集合的size()可以确切知道元素的个数 
4:集合有多种实现方式和不同适用场合,不像数组仅采用顺序表方式 
5:集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性即可实现各种复杂操作,大大提高了软件的开发效率

List集合

此图可用Windows系统自带画图工具查看比较清晰

有序列表,允许存放重复的元素; 
实现类: 
ArrayList:数组实现,查询快,增删慢,轻量级;(线程不安全)
LinkedList:双向链表实现,增删快,查询慢 (线程不安全)
Vector:数组实现,重量级  (线程安全、使用少)

而在LinkedList的底层是一种双向循环链表。在此链表上每一个数据节点都由三部分组成:前指针(指向前面的节点的位置),数据,后指针(指向后面的节点的位置)。最后一个节点的后指针指向第一个节点的前指针,形成一个循环。

 

本文由美洲杯赌球发布于计算机教程,转载请注明出处:Java集合详解

TAG标签: 美洲杯赌球
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。