新手看Java中的集合类(一)

版权声明:随意转载 https://blog.csdn.net/bigcupwater/article/details/78195187

写在前面

  只是对集合框架有一个大致的认识介绍,并没有深入展开。之后会补上。

集合类

  数组用于存放一组数据,但是其最大的局限就是长度固定。为此,Java 实用类库(java.util)提供了一套完整的容器类来解决这个问题。其中基本类型为List、Set、Queue、Map,这些对象类型就称为集合类。简单说集合类就是 Java 中数据结构的实现(官方出品)。

泛型

  这里简单讲清楚泛型的问题,使用最 ArrayList 创建一个容器,用来存放 Apple 类的多个对象和 Orange 类的一个对象。因为Arrylist 中可以存放的是任意类型的对象,所以可以同时存放 Apple 和 Orange 的对象,但是在使用 get() 方法获得容器中的对象去调用对象方法的时候,取到 Orange 的对象元素时会抛出 ClassastException 异常,因为 Orange 类和 Apple 类毛关系都没有。

class Apple {
    public void fun(){
        System.out.println("苹果类的方法");
    }
}

class Orange {}

public class Test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Apple());
        list.add(new Apple());
        list.add(new Apple()); // 向 list 中添加3个 Apple 对象
        list.add(new Orange()); // 向 list 中添加一个 Orange 对象

        for (int i = 0; i < list.size(); i++) {
            ((Apple)list.get(i)).fun(); // 取出容器中的对象是 Object 类型
                                        // 必须向下强制转换为 Apple 类,才可以去调用 fun() 方法
        }
    }
}
 

  解决办法就是,约束容器中只能存放我规定的类产生的对象,也就是所谓的泛型。在左右侧添加 <> 尖括号里面写允许存入的数据类型(只能是类,基本数据类型不可以)。这个时候添加 Orange 对象时会直接报错。但是允许向容器中添加 Apple 子类,Apple 父类不可以。

  ArrayList<Apple> list = new ArrayList<Apple>();

两大概念 Collection、Map

Java 集合类的作用是保存对象,其中分为两大阵营:(1) Collection 接口,(2) Map 接口;

  • Collection 接口,一个独立元素的序列,每次操作是以一个对象为单位的。其中包含三大子接口:
    • List:必须按照插入顺序保存元素;
    • Set : 不能有重复元素;
    • Queue :按照排队规则来确定对象的产生顺序(先进先出);
  • Map 接口,一组成对的“键值对”对象,允许使用键来查找值。
    接口关系

List

  List 可以将元素维护在特定的序列中,List 接口在 Collection 接口的基础上扩展了额外的方法。为了使用这些方法,我们在定义使用时基本上都用 List 接口做引用,List 接口实现子类去定义对象,List<String> strs = new ArraList<String>();
首先记住 List 的两个实现子类,使用方式大同小异:

  • ArrayList ,随机访问元素快,但是插入和移除元素慢;
  • LinkedList,插入删除快,优化了顺序访问,但是随机访问慢;

重要方法:
1. public boolean add(E e),添加元素;
2. public boolean contains(Object o),是否包含元素 o;
3. public boolean remove(Object o) ,删除元素 o;
4. public Object[] toArray(),将 List 转变为对象数组;
5. public Iterator iterator(),返回按适当顺序在列表的元素上进行迭代的迭代器。

    List<String> strs = new ArrayList<>(); // LinkedList也可以实现
        strs.add("hello");
        strs.add("world"); // 添加元素
        strs.add("name");
        strs.contains("hello"); // 输出为true,即使参数是一个new String("hello"),结果也为true.
                                // 因为 String 已经重写了equals方法
        strs.remove("world");
        Object[] obj = strs.toArray(); // 变为Object类型的对象数组

        Iterator<String> it = strs.iterator(); // 返回一个iterator对象用于迭代
        // 迭代输出
        while (it.hasNext()) { // 若下一元素不为空
            String str = it.next(); // 取出放入 str
            System.out.println(str); // 输出
        }

迭代器 Itrator

  迭代器是一个对象,用于遍历并选择序列中的对象。但是仅仅是单向移动,从第一个到最后一个其中重要方法:
1. public boolean hasNext();是否还有下一个元素;
2. public E next();返回迭代器的下一个元素;
3. public void remove();删除新近返回的元素,不常用;
  使用之前需要创建容器对应的迭代对象。Iterator<String> it = strs.iterator(); // 返回一个iterator对象用于迭代

双向移动的迭代器 ListItrator

  ListIterator 是一个更加强大的 Iterator 子类型,它只能用于各种 List 类的访问,可以双向移动。正反序输出的顺序不能颠倒。

    List<String> strs = new ArrayList<>();
        strs.add("hello");
        strs.add("world"); // 添加元素
        strs.add("name");

        ListIterator<String> it = strs.listIterator(); // 返回一个iterator对象用于迭代
        // 迭代输出
        while (it.hasNext()) { // 正序输出
            System.out.println(it.next() + ", " + it.nextIndex() + ", " + it.previousIndex());
            // 输出结果为:
            // hello, 1, 0
            // world, 2, 1
            // name, 3, 2
        }

        while (it.hasPrevious()) { // 反序输出
            System.out.println(it.previous() + ", " + it.previousIndex() + ", " + it.nextIndex());
            // 输出结果为:
            // name, 1, 2
            // world, 0, 1
            // hello, -1, 0
        }

Stack 栈 是具体的一个类,不是接口

  是一种先进后出的数据集合,
重要方法:
1. public E push(E item);压栈操作,将数据“放进”栈中;
2. public E pop();出栈操作,将数据从栈顶取出;
3. public E peek();查看栈顶元素,但是不弹出;

    Stack<String> strs = new Stack<String>();
        strs.push("a"); // 入栈
        strs.push("b");
        strs.push("c");
        System.out.println(strs); // 直接输出栈是在按照顺序push输出的
        System.out.println(strs.peek()); // 查看栈顶元素不会弹出
        System.out.println(strs.pop()); // 弹出栈顶元素
        System.out.println(strs.pop());
        System.out.println(strs.pop());
        System.out.println(strs.pop()); // 空栈异常EmptyStackException

栈

Set

  Set 是 Colllection 的子接口,但是没有对父接口进行扩展。Set 不保存重复的元素,用法同 List。
关注两个实现子类:

  • HashSet,按照 Hash 算法来存储集合中的元素,因此具有良好的存取和查找性能。但它不能保证元素的排列顺利,顺序可能与添加顺序不同,也可以保存 null 值。
  • TreeSet,将元素存储在红-黑树数据结构中,可以确保集合元素处于排序状态。
    • TreeSet的重要方法:
      1. public E first();返回集合中的第一个元素。
      2. public E last();返回集合中的最后一个元素。
      3. public E lower(E e);返回集合中位于指定元素之前的元素(一个),参数可以是不属于集合中的元素。
      4. public E higher(E e);返回集合中位于指定元素之后的元素(一个),参数同上。
    Set<String> strs = new HashSet<String>();
        strs.add("c"); 
        strs.add("c"); // 重复元素,只存储第一个元素
        strs.add("a");
        strs.add("b");
        strs.add("d");
        System.out.println(strs);
//****************************************************//
    TreeSet<String> strs = new TreeSet<String>(); // 要用到TreeSet自己的方法,引用必须treeSet
        strs.add("a");
        strs.add("b");
        strs.add("c");
        strs.add("d");
        strs.add("e");
        System.out.println(strs.first()); // 输出 a
        System.out.println(strs.last()); // 输出 e
        System.out.println(strs.lower("c")); // 输出 b
        System.out.println(strs.higher("c")); // 输出 d

Map

  Map 用于保存具有映射关系的数据,因此 Map 集合里保存着两组值(key, value)。key 不允许重复, value 允许重复。
两个子类:

  • HashMap;最多有一个key-value的key为null,可以有无数个value为null;
  • TreeMap;存储数据时,根据key对节点进行排序。

重要方法:
1. public V put(K key, V value);添加数据。
2. public V get(Object key);根据键值取数据
3. public boolean containsValue(Object value);查询是否有“值”;
4. public boolean containsKey(Object key);查询是否有“键”;

    Map<Integer, String> strs = new HashMap<Integer, String>();
        strs.put(1, "a");
        strs.put(2, "b");
        strs.put(3, "c");
        System.out.println(strs.get(4)); // 若键值不存在返回null
        System.out.println(strs.containsKey(1)); // true
        System.out.println(strs.containsValue("a")); // true

Queue 队列 一个接口

  队列是一个先进先出的容器,
重要方法:
1. public boolean add(E e);将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。
2. public boolean offer(E e);将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于 add(E),后者可能无法插入元素,而只是抛出一个异常。
3. public E peek();获取但不移除此队列的头;如果此队列为空,则返回 null。
4. public E element();获取,但是不移除此队列的头。此方法与 peek 唯一的不同在于:此队列为空时将抛出一个异常。
5. public E poll();获取并移除此队列的头,如果此队列为空,则返回 null。

    Queue<String> strs = new LinkedList<String>(); // LinkedList 实现了 Queue接口
        strs.add("a"); // 先进入元素是队列头
        strs.add("b");
        strs.offer("c"); // 插入元素到队列尾
        System.out.println(strs.peek()); // 查看不移除队列头,队列为空返回null
        System.out.println(strs.element()); // 查看不移除队列头,比起peek(),队列为空会抛出异常
        System.out.println(strs.poll()); // 查看并移除队列头

队列

小结

  • Collection 保存单一的元素,而 Map 保存相关联的键值对;
  • 使用泛型可以指定容器中存放的对象类型,容器不能容纳基本类型数据,可使用其对应包装类;
  • 如果进行大量的随机访问,就使用 ArrayList;如果经常插入或删除元素,就用 LinkedList;
  • 各种 Queue以及栈的行为,由 LinkedList 提供支持;
  • Map是一种将对象与对象相关联的设计。HashMap 设计用来快速访问;而TreeMap 保持键始终处于排序状态,所以没有 HashMap 快。LinkedHashMap 保持元素插入的顺序,但也通过散列提供了快速访问的能力。
  • Set不接受重复的元素。HashSet 提供最快的查询速度,而TreeMap 保持元素处于排序状态。LinkedHashSet以插入顺序保存元素。
    Java集合框架简单版,橙色的代表具体的类,其余为接口。Vectro 不常用在此未说明,直接使用栈就可以。
    集合框架

猜你喜欢

转载自blog.csdn.net/bigcupwater/article/details/78195187
今日推荐