7.Java容器详解

Java里面的容器是核心概念,这个是面向对象区别C语言的主要区别(这个是我个人认为的,当然区别还有很多)


7.Java容器详解_第1张图片
549734-20160920135339059-1268675998.png

基本从学习java的第二天就会接触容器的概念,包括List、Vector(JDK1.5后基本不再用了)、ArrayList、HashMap等等。有了容器,在日常开发中能很容易把业务逻辑融合到容器中,能替代数组的大部分操作。
谈到数组,估计很多人第一印象是多维数组循环是多么的复杂,我当时学C时,二维数组就基本把人搞晕了,不过到Java里面,因为容器的存在,数组一般不会用到,多数都用容器替代,主要原因是数组初始化时需要定义数组长度,而容器则不需要,基本是可变长度。定义一个可变长度的数组还是比较麻烦的。

上面那个图中,其中淡绿色的表示接口,红色的表示我们经常使用的类。

基本概念

Collection
一个独立元素的序列,这些元素都服从一条或多条规则。其中List必须按照插入的顺序保存元素、Set不能有重复的元素、Queue按照排队规则来确定对象的产生顺序(通常也是和插入顺序相同)
Map
一组成对的值键对对象,允许用键来查找值。ArrayList允许我们用数字来查找值,它是将数字和对象联系在一起。而Map允许我们使用一个对象来查找某个对象,它也被称为关联数组。或者叫做字典。

List主要用法
代码参见:com.critc.container.ListTest.java

 public static void main(String[] args) {
        // List基本操作
        List list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        List list2 = new ArrayList<>();
        //第一种循环输入方式
        for (String str : list) {
            System.out.println("第一种输出list值:" + str);
        }

        //第二种循环输出方式
        for (int i = 0; i < list.size(); i++) {
            String str = list.get(i);
            System.out.println("第二种输出list值:" + str);
        }

        //第三种循环输出方式
        Iterator it = list.iterator();
        while (it.hasNext()) {
            System.out.println("第三种输出list值:" + it.next());
        }
    //第四种循环输出方式
   list.forEach(str -> System.out.println("JDK8中输出list值:" + str));
    }

List在使用过程中有个陷阱,就是remove方法,平时想从list列表中直接删除一个值,结果循环后发现不对,原理就是每删除一个元素,该list的size值变化了,导致后续的循环错位。
代码参见:com.critc.container.ListRemoveTest

 public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");

       /* for (int i = 0; i < list.size(); i++) {
            String str = list.get(i);
            list.remove(str);
            System.out.println("剩余元素:" + list.toString());
        }*/

        //从list的最后一个元素进行循环
        for (int i = list.size() - 1; i >= 0; i--) {
            String str = list.get(i);
            list.remove(str);
            System.out.println("剩余元素:" + list.toString());
        }
    }

** 解决这个问题的方式就是list进行倒序循环,保证删除一个元素后整个list的顺序是不变的,这就可以正常解决问题了**

set主要用法

set区别list的主要原因就是set不允许对象重复,list是可以的。
代码参见:com.critc.container.SetTest

 public static void main(String[] args) {
        Set set = new HashSet();
        set.add("abc");
        set.add("cde");
        set.add("efg");
        set.add("fgh");
        set.add("abc"); //重复的abc,set会自动将其去掉
        System.out.println("size=" + set.size());
        Iterator it = set.iterator();
        while (it.hasNext()) {
            System.out.println("输出set的值:" + it.next());
        }
    }

queue主要方法

queue这个用的比较少,只允许在表的一端进行插入,而在另一端进行删除元素的线性表,一般用在模拟一个队列,从对头获取并删除(pool()),从队尾加入(offer())。
代码参见:com.critc.container.QueueTest

 public static void main(String[] args) {
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        Queue queue = new LinkedList();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for (String q : queue) {
            System.out.println("循环队列:" + q);
        }
        System.out.println("---------------------");
        System.out.println("获取第一个元素并把这个删除:" + queue.poll()); //返回第一个元素,并在队列中删除
        System.out.println("---------------");
        System.out.println("获取第一个元素=" + queue.element()); //返回第一个元素,不移除,使用element()或peek()方法
        for (String q : queue) {
            System.out.println(q);
        }
    }

Map主要方法

Map集合的key具有一个特征:所有的key不能重复,且key之间没有顺序(TreeMap是有顺序的),如果将Map集合的所有key集中起来,那这些key就组成了一个set集合,则map集合提供了keySet()方法返回所有key组成的集合。
代码参见:com.critc.container.HashMapTest

public static void main(String[] args) {
        HashMap scores = new HashMap<>();
        scores.put("语文", 89.0);
        scores.put("数学", 83.0);
        scores.put("英文", 84.0);
        System.out.println(scores.values());
        Set> entrySet = scores.entrySet();
        for (Map.Entry entry : entrySet) {
            System.out.println("取得key:" + entry.getKey());
            System.out.println("对应的value为:" + entry.getValue());
        }
        System.out.println("是否包含key:"+ scores.containsKey("语文"));
        System.out.println("是否包含value:"+ scores.containsValue(83.0));
    }

Hashmap的主要方法有put(),containsKey().containsValue()
跟map有关的还有LinkedHashMap和TreeMap,这两个是有序的HashMap,具体区别找度娘即可。

java的容器是非常复杂的,这里面还涉及一个线程安全和线程不安全的概念,比如HashMap和HashTable,HashTable是线程安全的,可以在不同线程中通过HashTable来共享对象。普通开发中用HashMap足够,很少会用到HashTable的。我遇到过的用HashTable 的例子是通过HashTable来存储多个数据源对象,在多线程中调用HashTable来获取不同的数据源,一开始是用HashMap,后来发现存在数据源获取错误的时候,最后才发现是线程安全问题。

源码下载

本例子详细源码

你可能感兴趣的:(7.Java容器详解)