集合

本文深入讲解Java集合框架,包括Collection、List、Set、Map等核心接口及其实现类的特点与应用场景,对比不同集合类型的优缺点。

一、概述
集合框架是Java一块很重要的内容,对常用的数据结构做了规范和实现。对象封装了数据,许多对象则构成了所谓集合。Java集合类库构成了集合类的框架。它为集合的实现者定义了大量的接口和抽象类,并且对其中的某些机制给予了描述。
集合框架的接口和实现类:
集合框架的接口和实现类

二、Iterator接口
Iterator接口与Collection系列、Map系列的集合不一样:Collection系列集合、Map系列集合主要用于盛装其他对象,而Iterator则主要用于遍历(即迭代访问)Collection集合中的元素,Iterator对象也被称为迭代器。[]
Iterator接口定义了四个方法
–boolean hasNext():如果被迭代的集合还元素没有被遍历,则返回true。
–Object next():返回集合里下一个元素。
–void remove() :删除集合里上一次next方法返回的元素
–void forEachRemaining(Consumer action):这是Java 8为Iterator新增的默认方法,该方法可使用Lambda表达式来遍历集合元素。

/**
 * @author shen
 * @desc Iterator接口
 * @date 2016年8月23日
 */
public class IteratorTest {

    public static void main(String[] args) {

        //Iterator是Collection父接口,可如此创建集合
        Collection<Object> animals = new HashSet<>();

        //添加元素
        animals.add("cat");
        animals.add("dog");
        animals.add("pig");

        //使用Lambda表达式遍历集合(java1.8新特性)
        animals.forEach(obj -> System.out.println("Lambda迭代输出:" + obj));

        //iterator()方法获取迭代器
        Iterator<Object> data = animals.iterator();
        while(data.hasNext()){
            Object subData = data.next();
            if("cat".equals(subData)){
                data.remove();//移除元素
            }
            System.out.println("迭代器输出:" + subData);
        }
        System.out.println(animals);

    }
}

输出:
这里写图片描述

三、Collection接口
Collection不提供接口的任何直接实现,一个Collection代表一组Object,但它提供更加具体的子接口如List和Set,而继承自它们的 ArrayList, Vector, HashTable, HashMap等实现类才可被实例化。
1、List接口
List是一个有序集合(ordered collection)。元素可以添加到容器中某个特定的位置。将对象放置在某个位置上可以采用两种方式:使用整数索引或使用列表迭代器。[引 java核心技术]
List接口实现类主要有:ArrayList、Vector、LinkedList。
(1)ArrayList
ArrayList是List接口的可变数组的实现,其操作基本是对数组的操作,ArrayList是线程不安全的。
ArrayList包装了许多的方法,包括元素的增加移除、插入移动、转换数组等等:

/**
 * @author shen
 * @desc
 * @date 2016年8月23日
 */
public class ListTest {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("1");//使用list时默认长度置为10
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");

        System.out.println("list输出:"+list);
        list.remove(4);//移除元素
        System.out.println("移除元素之后的list:"+list);
        Object[] arr = list.toArray();//转换为数组
        System.out.println("数组元素输出:"+arr[0]);

        List<String> c = new ArrayList<>(4);//预计有4个元素而创建
        c.add("6");
        c.add("7");
        c.add("8");
        c.add("9");

        c.add("10");//超过5个元素list会增加原来长度一半个元素,目前即长度为6
        list.addAll(c);//增加一组数据,数据类型应相同
        System.out.println(list);

        Iterator<String> data = list.iterator();//获取迭代器
        System.out.println("迭代输出:");
        data.forEachRemaining(action -> System.out.print(action+" "));
    }
}

输出:
这里写图片描述
ArrayList的各种操作虽然很方便,但是ArrayList的插入和删除,会导致内部数据大量移位,而扩容则需要新建一个ArrayList将原来的数据复制过去,会影响性能。如果我们已经知道需要的元素个数,我们可以初始化时指定ArrayList的容量,这样可以有效的避免数组多次扩充,从而提高效率。
(2)Vector
Vector类提供了实现可增长数组的功能,随着更多元素加入其中,数组变的更大。在删除一些元素之后,数组变小,而不像ArrayList的扩容方式,基本用法与ArrayList相同。Vector是同步类,是线程安全的。
(3)LinkedList
LinkedList是list的链表实现,列表中的每个节点都包含了对前一个和后一个元素的引用,除了大部分与ArrayList相同的方法,LinkedList还有一些其特有的方法,并且LinkedList在添加和删除元素时具有比ArrayList更好的性能,但在get数据时更慢。LinkedList适用于没有大规模的随机读取,大量的增加/删除操作。[]

public class LinkTest {

    public static void main(String[] args) {

        LinkedList<String> link = new LinkedList<>();
        link.add("a");
        link.add("b");
        link.add("c");
        link.add("d");
        link.add("e");
        System.out.println("第一个元素:"+link.getFirst()+"  最后一个元素:"+link.getLast());

        link.remove(1);
        System.out.println(link);

        link.add(3, "zhiding");
        System.out.println(link);
    }
}

输出:
这里写图片描述

2、Set接口
由于Set接口提供的数据结构是数学意义上集合概念的抽象,因此它需要支持对象的添加、删除,而不需提供随机访问。Set具有与Collection完全一样的接口,因此没有任何额外的功能。实际上Set就是Collection,只是行为不同。Set不包含重复的元素。
Set的实现类主要有:HashSet,TreeSet,LinkedHashSet
(1)HashSet
不保证set的迭代顺序,不保证该顺序永恒不变,因此HashSet也没有get方法。此类允许使用null元素,底层是使用HashMap实现的。

public static void main(String[] args) {

        HashSet<String> set = new HashSet<>();
        set.add("adf");
        set.add("bhf");
        set.add("c32");
        set.add("c32");//有重复元素,添加不了
        set.add(null);//null也只允许只有一个
        System.out.println(set);

        for(String str : set){
            System.out.print(str +" ");
        }
        System.out.println();
        Iterator<String> iterator = set.iterator();
        while(iterator.hasNext()){
            String data = iterator.next();
            System.out.print(data +" ");
        }

    }

输出:
[null, bhf, adf, c32]
null bhf adf c32 
null bhf adf c32 

(2)TreeSet
TreeSet元素自然排序,底层是使用TreeMap实现的,自定义要显示Comparable接口。TreeSet可以给集合中的元素进行指定方式的排序,保证元素唯一性。

/**
 * @author shen
 * @desc 测试类,实现Comparable<T>接口
 * @date 2016年8月24日
 */
public class User implements Comparable<User>{

    private String name;
    private int age;

    //构造
    public User(String name,int age){
        this.name = name;
        this.age = age;
    }

    //实现类
    @Override
    public int compareTo(User user) {  
        if(user == null)  
            throw new NullPointerException();  
        if(this.age > user.age)  
            return 1;  
        if(this.age < user.age)  
            return -1;  
        return 0;  
    }

    //重写toString
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }  
}

//测试
public static void main(String[] args) {

        Set<User> set = new TreeSet<User>();

        User user1 = new User("Tom", 20);
        User user2 = new User("Jack", 21);
        User user3 = new User("Dave", 22);
        User user4 = new User("Jane", 12);

        set.add(user1);
        set.add(user1);//重复,添加不了
        set.add(user2);
        set.add(user3);
        set.add(user4);

        System.out.println("按年龄大小输出:");
        System.out.println(set);

    }

输出
按年龄大小输出:
[User [name=Jane, age=12], User [name=Tom, age=20], User [name=Jack, age=21], User [name=Dave, age=22]]

(3)LinkedHashSet
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。[]

四、Map接口
在Collection实现中保存的直接是一个个对象,二在Map实现中保存的是一对对象,以键值对key-value的方式关联着。Map的常用实现类有HashMap,HashTabel和TreeMap。
1、HashMap
HashMap是基于哈希表的Map接口的非同步实现,其中元素表现无序,特别是它不保证该顺序恒久不变。HashMap会利用对象的hashCode来快速找到key。

public static void main(String[] args) {

        //使用实现类创建,键值指定对象类型
        HashMap<String, String> map = new HashMap<>();
        map.put("name", "shen");
        map.put("age", "20");
        map.put("age", "19");//相同键多次存入数据覆盖
        map.put("weight", "100");
        map.put(null, "空");//允许空键值
        map.put(null, null);
        System.out.println(map);

        //对map集合的遍历,可取出具体的键和对应值
        for(Entry<String, String> element:map.entrySet()){
            String key = element.getKey();
            String value = element.getValue();
            Class<? extends Entry> classData = element.getClass();
            System.out.println(key + "---- " + value + "---- " + classData.getName());
        }

        //使用接口创建,不关心具体实现,只有在使用才具体实现
        //键值的值一般设为Object,不关心什么类型的数据,当然,获取需要具体数据类型或对象需要转化
        Map<String, Object> mapData = null;//new HashMap<>();
        mapData = new HashMap<>();
        mapData.put("name", "Jack");
        mapData.put("age", 21);
        mapData.put("weight", 110.5);
        System.out.println(mapData);
        System.out.println("获取name值:" + mapData.get("name"));
        Set<String> keys = mapData.keySet();
        System.out.println("获取所有key:" + keys);
        Collection<Object> values = mapData.values();
        System.out.println("获取所有value:" + values);

    }

输出:
{null=null, name=shen, weight=100, age=19}
null---- null---- java.util.HashMap$Node
name---- shen---- java.util.HashMap$Node
weight---- 100---- java.util.HashMap$Node
age---- 19---- java.util.HashMap$Node
{name=Jack, weight=110.5, age=21}
获取name值:Jack
获取所有key:[name, weight, age]
获取所有value:[Jack, 110.5, 21]

2、HashTabel
HashTable在很大程度事实上和HashMap的实现差不多,主要区别是HashMap采用异步处理方式,性能更高,而HashTabel采用同步处理方式,性能较低。HashTabel属于线程安全类而HashMap属于线程不安全类。[参考]

3、TreeMap
TreeMap是可排序的Map集合按照集合中的key进行排序,key不允许重复。TreeMap是红黑树基于Map接口的实现。关于TreeMap红黑树参考,初次接触不容易理解,多查资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值