JAVA类集框架

一.基本概念

  在讲解类集概念前,先来思考这样一个问题, 如果现在要保存一组对象, 按照之前的做法则只能使用对象数组,一但是使用对象数组操作本身有一个限制, 就是数组有长度的限制:而通过一些数据结构的操作,如链表,则可以完成动态对象数组的操作,但是这些如果全部由开发人员来做,则肯定是比较麻烦的。
  类集框架恰好解决了 上面的难题,所谓类集就是一个动态的对象数组,是对一些实现好的数据结构进行了包装,这样在使用时就会非常方便,而且最重要的是类集框架本身不受对象数组的长度限制

注:数组最大的缺点之一就是会受到长度的限制

二.类集框架的组成部分

  

三.被设计成的类集框架有以下的几个特性

(1)框架必须是高性能的。对基本类集(动态数组,连接表,树和散列表)的实现须是高效率的。一般很少需要人工对这些“数据引擎”编写代码。

(2)框架必须允许不同类型的类集以相同的方式和高度互操作方式工作。

(3)类集必须是容易扩展和修改的。所以很多被设计成一组接口方便具体类实现。(可以参考里氏替换原则)

四.类集框架的一些主要的接口和一些实现类

类集框架:jdk提供的一系列类和接口,位于java.util包当中,主要用于存储和管理对象,主要分为三大类:集合、列表和映射。

集合Set:用于存储一系列对象的集合。无序、不允许重复元素

列表List:用来存储有顺序的一组数据的集合。有序

映射Map:以键值对的方式进行数据存储的集合。

Collection接口是类集单值保存的最大父接口。

Map接口是类集键值对保存的最大父接口。

五.一些经常使用的接口的方法

Collection接口

定义如下:

public interface Collection<E> extends lterable<E>.

(Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,且使得所有实现了Collection接口的具体类都能够迭代输出)

一般运用向上转型为Collectiion实例化对象。

  1 public boolean add(E e):添加一个元素
  2 public void clear():清空集合中所有的元素
  3 public boolean remove(E e):移除集合中指定的元素
  4 public boolean contains(E e):检查集合中是否包含指定的对象
  5 public boolean isEmpty():判断集合是否为空
  6 public void size():判断集合中元素的个数
  7 public Object[] toArray():把集合元素存储到数组中

List接口

注:JAVA中判断是否有重复的内容或者对象是通过equals和hashcode来判断的,所以一般自定义的类必须的覆写Object类中的这两个方法  。 一般排序时还要覆写compareTo()方法。

定义如下:

public interface List<E>extends Collection<E>.

List接口,其下面主要实现类有Vector集合,ArrayList集合,LinkedList集合,底层实现方式有数组,也有链表,它有如下特点:
(1)有序的集合,即存储和取出元素的顺序相同
(2)允许存储重复的元素
(3)有索引,可以使用普通的for循环遍历

List接口扩展了许多Collection的方法,下面是一些常用的方法。

  1.public void add(int index,E element): 在指定位置增加元素

  2.E get(int index): 返回指定位置的元素

  3.public int indexOf(Object o):返回指定位置的元素

  4.public ListIterator<E>listIterator():为ListIterator接口实例化。

  5.public E remove(int index):按指定的位置删除元素。

新的子类:ArrayList (很常用)

ArrayList 是List子类,可以直接通过对象的多态性为List接口实例化。

新的子类:LinkedList

LinkList表示的是一个链表的操作类,即Java中已经为开发者提供好了一个链表程序,开发者可以直接使用,而不用再重新开发。

常用的方法:

  1.public void addFirst(E o):在链表开头增加元素。

  2.public void addLast(E o);在链表结尾增加元素。

  3.public E removeFirst();删除链表的第一个元素。

  4.public E removeLast();删除链表的最后一个元素。

Set接口

  1.Set接口是无序的。

  2.Set是继承于Collection的接口。它是一个不允许有重复元素的集合。

  3.Set可以存储null值,但是null不能重复。

Set接口其实和List接口没有太大的区别。但Set接口的主要方法与Collection是一致的,也就是说Set接口并没有对Collection接口进行扩充。

Set接口的常用子类:

  1.HashSet(散列存放):

    里面不能存放重复元素,而且采用散列存放,所以没有顺序。

  2.TreeSet

    有序排序,如果要排序自定义的类,则必须实现Comparable接口才可以正常使用,且覆写compareTo()方法。

Map接口

  上面的接口都属于单值的操作,即每次只能操作一个对象,而Map与它们不同,每次操作的都是一对对象,即二元偶对象,Map中的每个元素都使用“Key——>value"的形式存储在集合中。

定义如下:

  public interface Map<k,v>

 

Map接口中的方法

 

 

【注意】:Map集合通过entrySet()方法转换成Set集合,Set集合中元素的类型是:Map.Entry<K,V>。Map.Entry<K,V>:和String一样是一个类型的名字,是Map中的静态内部类(内部接口)

 

 

 

 

 Map集合的继承结构

 

 

 

 

 【注意】:非线程安全的类采用异步处理方式,性能更高。而线程安全的类采用同步处理方式,性能较低。

使用Map接口的注意事项

  对于Map接口来说,其本身是不能直接使用迭代(如Iterator, foreach) 进行输出的,因为Map中的每个位置存放的是一对值(key > value),而Iterator中每次只能找到一个值。所以,如果非要使用送代进行输出,则必须按照以下的步骤完成(以Tertor输出方法为例)。

(1)将Map的实例通过entrySet0方法变为Set接口对象。
(2)通过Set接口实例为Iterator实例化。
(3)通过Iterator迭代输出,每个内容都是Map. Entry的对象。
(4)通过Map.Entry进行key ——> value的分离。
Map中的每对数据都是通过Map.Entry保存的,所以如果最终要进行输出的话也应该使用Map.Entry完成。

六.集合的输出

  在类集中提供了4中常见的输出方式

  1.Iterator:迭代输出,是使用最多的输出方式。

  2.ListIterator:是Iterator的子接口,专门用于输出List中的内容。

  3.Enumeration:是一个旧的接口,功能与Iterator类似。

  4.foreach:JDK1.5之后提供的新功能,可以输出数组或集合。

迭代输出Iterator 

  迭代模式指的是依据指针依次判断是否有数据,如果有数据则进行数据的取出。

  定义如下:

  public interface Iterator<E> 

 Iterator接口中的常用方法:
  1.public boolean hasNext() ; 判断是否有下一个值。
  2.public E next() ; 取出当前元素。
  3.public void remove() ; 移除当前元素。
import java.util.*;
public class TestIterator {
    public static void main(String[] args) {
        ArrayList<String> a = new ArrayList<String>();
        a.add("aaa");
        a.add("bbb");
        a.add("ccc");
        System.out.println("Before iterate : " + a);
        Iterator<String> it = a.iterator();
        while (it.hasNext()) {
            String t = it.next();
            if ("bbb".equals(t)) {
                it.remove();
            }
        }
        System.out.println("After iterate : " + a);
    }
}

 

运行结果:

 

【注意】正常情况下,一个集合要把内容交给Iterator输出,但是集合操作也存在一个remove()方法,如果在使用Iterator输出时,由集合调用自身的删除方法,运行时也会错误。
当内容被删除之后就终止了。这就是因为集合本身的内容被破坏掉了,所以迭代将出现错误停止输出。

 


 

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;

public class MapDemo01 {
    public static void main(String[] args) {
        Map<String,String> map=null;
        map = new HashMap<>();
        map.put("mldn","www.mldn.cn");
        map.put("zky","2020110261");
        Set<Map.Entry<String,String>>allset=null;
        allset = map.entrySet();
        Iterator<Map.Entry<String,String>> iter=null;
        iter=allset.iterator();
//下面的经典的迭代输出格式
while (iter.hasNext()){ Map.Entry<String,String> me=iter.next(); System.out.println(me.getKey()+"-->"+me.getValue()); } } }

 

运行结果:

 

 

 

 

双向迭代输出ListIterator

  ListIterator是Iterator的子接口,主要作用是为List接口实现双向迭代。

  主要添加方法如下;

    1.public boolean hasPrevious();判断是否有上一个元素

    2.public E previous();取出当前元素

    3.public int nextIndex();取出下一个元素的索引号

    4.public int previousIndex();返回上一个元素的索引号

     双向迭代

class ListIteratorDemo01{
    public static void main(String[] args) {
        List<String> all = new ArrayList<>();
        all.add("hello");
        all.add("_");
        all.add("world");
        ListIterator<String> iter = all.listIterator();
        System.out.print("由前向后输出");
        while (iter.hasNext()){
            System.out.print(iter.next()+"、");
        }
        System.out.print("\n由后向前输出");
        while (iter.hasPrevious()){
            System.out.print(iter.previous()+"、");
        }
    }
}

   运行结果:

 

 

 

上面的程序实现了双向的迭代输出,但是此种输出方式只有List接口才可以做到。

 foreach输出格式

  for(类 对象 :集合){

  //集合操作

  }

   此方法与数组的foreach格式一样。

class ListIteratorDemo01{
    public static void main(String[] args) {
        List<String> all = new ArrayList<>();
        all.add("hello");
        all.add("_");
        all.add("world");
        for(String str : all){
                System.out.print(str+"、");
        }
    }
}

Enumeration接口

  Enumeration已经被淘汰了,此接口跟Iterator接口差不多,但Iterator接口中有删除数据的方法,且一些方法名称更短。

七.集合工具类Collections

  1.public static void swap(List list, int i, int j) :将指定列表中的两个索引进行位置互换

  2.public static void  sort(List<T> list) :按照列表中元素的自然顺序进行排序

 【注意】如果是要排序一个自定义的类,则一定要实现Comparable接口,否则会出现类型转换异常

  3.public static void shuffle(List list):随机置换  

  4.public static void reverse(List list)  :反转

  5.public static void fill(List list, Object obj) :使用指定的对象填充指定列表的所有元素

  6.public static void copy(List dest, List src) :是把源列表中的数据覆盖到目标列表

  7.public static int  binarySearch(List list, Object key) 使用二分查找法查找指定元素在指定列表的索引位置

  常量
  1.public static final List EMPTY_LIST 返回一个空的List集合

  2.public static final List EMPTY_SET 返回空的Set集合

  3.public static final List EMPTY_MAP 返回空的Map集合

可以观察到此接口中的方法和常量全是static定义的,所以可以直接通过类实现,而不需要实例化对象。

八.Stack类 

Stack是栈;特点是:先进后出。
(如在浏览器中存在的一个“后退”按钮,每次后退都是后退到上一个页面,这实际上就是一个栈的应用,采用就是先进后出的操作)

Stack类的一些方法;

  public E push(E item)  把项压入堆栈顶部。
  public E pop()  移除堆栈顶部的对象,并作为此函数的值返回该对象。
  public E peek()  查看堆栈顶部的对象,但不从堆栈中移除它。
  public boolean empty()  测试堆栈是否为空。
  public int search(Object o)  返回对象在堆栈中的位置,以 1 为基数。

九.本章类集框架要点

  1.类集的目的是用来创建动态的对象数组操作。

  2.Collection接口是类集中的最大单值操作的父接口,但是一般的开放中不会直接使用,而是使用List接口或Set接口。

  3.List接口扩展了Collection接口,里面的内容是允许重复的。其常用的子类:ArrayList和Vector,在开发中ArrayList性能较高,为异步处理。而Vecter性能较低,为同步处理。

  4.对象是否是同一个主要是依靠Object类中的eaquals()和hashCode()方法来区分是否是同一个对象。

  5.Set接口的常用子类有HashSet(散列存放,无序)和TreeSet(顺序存放,有序,使用Comparable接口进行排序操作)。

  6.List集合可以使用ListIterator接口进行双向的输出操作。

  7.Map接口中存放的是一对内容,采用键值对的方式存储,且每一个“Key->value”都是一个Map.Entry对象的实例,如果要输出则必须将其转换为Set接口对象,然后通过Iterator实例化输出。

  8.类集中提供了Collections工具类完成了类集的相关操作。

  9.使用类集可以方便的表示出一对多及多对一的关系。即在一个类中的属性再定义相关类型的类集。