Java 集合类

本文详细介绍了Java集合框架的各种数据结构,包括List、Set、Map及其具体实现类的特点和使用方法。对比了ArrayList与LinkedList,HashSet与TreeSet的优劣,并探讨了HashMap与Hashtable的异同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述
图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,虚线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection/Map等。

  1. List
    List 有序、可重复、线性存储
    LinkedList 链表实现的List,易于增删
    ArrayList 数组实现的List,易于查询,不易于增删、线程不安全,轻量级
    Vector 数组实现的List,易于查询,不易于增删、线程安全,重量级
    实例:
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;

public class ArrayListDemo {
    public static void main(String[] args){
        Collection<String> collection=new ArrayList<String>();
        List<String> list=new ArrayList<String>();
        collection.add("1");
        collection.add("2");
        collection.add("3");
        collection.add("1");
        System.out.println("collection result is :"+collection);

        list.add("A");
        list.add("D");
        list.add("C");
        list.add("A");
        list.addAll(0,collection);
        System.out.println("list result is :"+list);

        list.remove(3);
        list.remove("A");
        list.removeAll(collection);
        System.out.println("the last list result is :"+list);

        List<String> sublist=list.subList(1, 3);//截取集合
        System.out.println("截取集合 :"+sublist);

        System.out.println("集合中指定位置的元素 :"+sublist.get(1));

        sublist.set(0, "Set");//设定指定位置的元素

        System.out.println("集合list中A的位置 :"+list.indexOf("A"));

        String arrString[]=list.toArray(new String[]{});
        for(String str:arrString){
            System.out.println(str+" ");
        }

        System.out.println("list 是否为空 :" + list.isEmpty());

        list.clear();

        System.out.println("list 是否为空 :" + list.isEmpty());
    }
}
  1. Set
    Set 无序、不可重复、允许有Null元素
    HashSet 快速定位一个元素、无序(顺序可能随时改变)、最多允许一个Null元素、线程不同步
import java.util.Set;
import java.util.HashSet;

class Person{
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name,int age){
        this.age=age;
        this.name=name;
        }
    public String toString(){
        return ("name:"+name+"age:"+age+'\n');
    }   
}

public class HashSetDemo {
    public static void main(String[] args){
        Set<Person> set=new HashSet<Person>();
        set.add(new Person("小米",21));
        set.add(new Person("大米",28));
        set.add(new Person("小米",21));
        set.add(new Person("玉米",21));
        set.add(new Person("麦子",23));
        System.out.println(set);
    }
}


首先输入顺序与输出顺序无关,然后有重复数据小米,因为new Person(“小米”,21)不是同一内存地址的对象,HashSet不认为他们相同。
原因:Person没有重写equals()方法,所以调用Object的方法,所以最好重写equals()方法。

import java.util.Set;
import java.util.HashSet;

class Person{
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name,int age){
        this.age=age;
        this.name=name;
        }
    public boolean equals(Object o){
        if(this==o){
            return true;
        }
        if(o==null){
            return false;
        }
        if(!(o instanceof Person)){
            return false;
        }
        Person per=(Person) o;
        if(this.name.equals(per.name) && this.age==per.age){
            return true;
        }
        else{
            return false;
        }
    }
    public int hashCode() {
        final int prime=13;
        int result=13;
        result=prime*result+((name==null)?0:name.hashCode());
        result=prime*result+age;
        return result;
    }
    public String toString(){
        return ("name:"+name+"age:"+age+'\n');
    }   
}

public class HashSetDemo {
    public static void main(String[] args){
        Set<Person> set=new HashSet<Person>();
        set.add(new Person("小米",21));
        set.add(new Person("大米",28));
        set.add(new Person("小米",21));
        set.add(new Person("玉米",21));
        set.add(new Person("麦子",23));
        System.out.println(set);
    }
}

重写后的结果,没有了重复!
程序设计时要将摸个对象保存到HashSet里,最好重写以上两个方法。
TreeSet 元素按序存放、默认升序

Set<Integer> test=new TreeSet<Integer>();
        test.add(1);
        test.add(3);
        test.add(9);
        test.add(7);
        test.add(6);
        test.add(6);
        System.out.println(test);

输出:1,3,6,7,9
重复元素无法输出、升序排列。

Set<Person> tset=new TreeSet<Person>();
        tset.add(new Person("小米",21));
        tset.add(new Person("大米",28));
        tset.add(new Person("小米",21));
        tset.add(new Person("玉米",21));
        tset.add(new Person("麦子",23));
        System.out.println(tset);

输出结果报错,原因:TreeSet集合只能对实现了Comparable接口的类的对象进行排序。

import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;

class Person implements Comparable<Person>{
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name,int age){
        this.age=age;
        this.name=name;
        }

    public int compareTo(Person per){
        if(this.age>per.age){
            return 1;
        }
        else if(this.age<per.age){
            return -1;
        }
        else{
            return this.name.compareTo(per.name);
        }
    }

    public String toString(){
        return ("name:"+name+"age:"+age+'\n');
    }   
}

public class HashSetDemo {
    public static void main(String[] args){
        Set<Person> tset=new TreeSet<Person>();
        tset.add(new Person("小米",21));
        tset.add(new Person("大米",28));
        tset.add(new Person("小米",21));
        tset.add(new Person("玉米",21));
        tset.add(new Person("麦子",23));
        System.out.println(tset);
    }
}
![已经按年龄排序!也没有重元素!](http://img.blog.youkuaiyun.com/20160422152303650)
  1. 集合的输入输出
    Iterator
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

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

        //System.out.println("collection result is :"+collection);

        list.add("A");
        list.add("D");
        list.add("C");
        list.add("A");
        list.addAll(0,collection);
        Iterator<String> it=list.iterator(); 
        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }

输出:1 2 3 1 A D C A;

Iterator<String> it=list.iterator(); 
        while(it.hasNext()){
            it.next();
            it.remove();
        }

用于删除元素。
Foreach

import java.util.Collection;
import java.util.List;
import java.util.ArrayList;

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

        //System.out.println("collection result is :"+collection);

        list.add("A");
        list.add("D");
        list.add("C");
        list.add("A");
        list.addAll(0,collection);
        for(String str:list){
            System.out.print(str+" ");
        }

输出结果:1 2 3 1 A D C A ;

  1. Map
    Map Key不允许重复,Value可以重复、Key决定存储对象在映射中的存储位置,这不是Key本身决定的,由散列技术进行处理。
    Map.Entry接口
    HashMap**删除添加、允许键值对为空,但键必须唯一。**非同步、无序(不保证改顺序永久不变)。
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.HashMap;
import java.util.Iterator;

public class HashMapDemo {
    public static void main(String[] args){
        Map<Integer,String> map=new HashMap<Integer,String>();
        //Map<Integer,String> map=new HashMap<Integer,String>();
        map.put(1, "清华大学");
        map.put(2, "北京大学");
        map.put(3, "宁波大学");
        map.put(4, "浙江大学");
        map.put(null, "清华大学");
        System.out.println(map.get(3));

        Set<Integer> set=map.keySet();
        Iterator<Integer> itKey=set.iterator();
        System.out.println("The key of Map :");
        while(itKey.hasNext()){
            System.out.print(itKey.next()+"  ");
        }
        System.out.println();

        Collection<String> c=map.values();
        Iterator<String> itValue=c.iterator();
        System.out.println("The value of Map :");
        while(itValue.hasNext()){
            System.out.print(itValue.next()+"  ");
        }
    }
}


Map本身不能直接使用Iterator进行输出,需要进行如下步骤:首先,Map实例通过entrySet()方法转换成Set集合;然后,由Set集合实例化Iterator;最后,通过Map.Entry的getKey()/getValue()分离Map集合的价值对。

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

public class HashMapDemo {
    public static void main(String[] args){
        Map<Integer,String> map=new HashMap<Integer,String>();
        //Map<Integer,String> map=new HashMap<Integer,String>();
        map.put(1, "清华大学");
        map.put(2, "北京大学");
        map.put(3, "宁波大学");
        map.put(4, "浙江大学");
        map.put(null, "清华大学");

        Set<Map.Entry<Integer,String>> set =map.entrySet();
        Iterator<Map.Entry<Integer,String>> it=set.iterator();
        System.out.println("The key---value of Map :");
        while(it.hasNext()){
            Map.Entry<Integer,String> mapEntry=it.next();
            System.out.println("  "+mapEntry.getKey()+"-----"+mapEntry.getValue());
        }
    }
}

这里的顺序是Hash运算导致的巧合,HashMap本身无序
foreach输出:

for(Map.Entry<Integer,String> mapEntry:map.entrySet()){
            System.out.println("  "+mapEntry.getKey()+"-----"+mapEntry.getValue());
        }

TreeMap**有序、添加删除和定位能力差**

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

public class HashMapDemo {
    public static void main(String[] args){
        Map<Integer,String> map=new HashMap<Integer,String>();
        //Map<Integer,String> map=new HashMap<Integer,String>();
        map.put(1, "清华大学");
        map.put(44, "北京大学");
        map.put(77, "宁波大学");
        map.put(20, "浙江大学");
        map.put(51, "清华大学");

        Set<Map.Entry<Integer,String>> set =map.entrySet();
        Iterator<Map.Entry<Integer,String>> it=set.iterator();
        System.out.println("The key---value of Map :");
        while(it.hasNext()){
            Map.Entry<Integer,String> mapEntry=it.next();
            System.out.println("  "+mapEntry.getKey()+"-----"+mapEntry.getValue());
        }

        Map<Integer,String> tmap=new TreeMap<Integer,String>();
        tmap.putAll(map);
        Set<Map.Entry<Integer,String>> tset =tmap.entrySet();
        Iterator<Map.Entry<Integer,String>> tit=tset.iterator();
        System.out.println("The key---value of Map :");
        while(tit.hasNext()){
            Map.Entry<Integer,String> tmapEntry=tit.next();
            System.out.println("  "+tmapEntry.getKey()+"-----"+tmapEntry.getValue());
        }
    }
}

有序且为升序、但Key不能够为null
因为Key的类型已经可比较,如果为自定义的类,就要实现Comparable接口,否则将出现异常转换!

class Test{
}

public class HashMapDemo {
    public static void main(String[] args){
        Map<Test,String> map=new HashMap<Integer,String>();
        map.put(new Test("jd"), "清华大学");
        System.out.println(map.get(new Test("jd")));
    }
}

输出为null
原因:自定义类没有像String等一样的缓冲池机制,map.put(new Test(“jd”))和map.get(new Test(“jd”)不是同一个对象。解决方法是重写重写equals()和hashCode()方法。
5. Collections
Collections集合工具类,对几何元素进行排序、查询和修改等操作。

  1. 其他
    向量类Vector**和ArrayList没有多大区别,线程安全、重量级**
    栈Stack类****empty()\peek()\pop()\push()\search()
    哈希表HashTable****Map子类、同步线程安全、不允许null键和null值
    HashMap和HashTable 区别
    首先:都是Map的实现类、HashMap线程不安全,性能相对较高;而HashTable 线程安全且同步,性能相对较低
    然后:HashMap的键值对可以为null,但键必须唯一,而HashTable不允许null键和null值
    什么时候使用Hashtable,什么时候使用HashMap
    基本的不同点是Hashtable同步HashMap不是的,所以无论什么时候有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。
    如果在将来有一种可能—你需要按顺序获得键值对的方案时,HashMap是一个很好的选择,因为有HashMap的一个子类 LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说HashMap更灵活。
    ArrayList与Vector的区别
    首先:都是List的实现类、都是有续集合,可重复,相当于动态数组;
    然后:ArrayList线程不安全,性能相对较高;而Vector线程安全且同步,性能相对较低
    还有:增长空间方法不同,Vector每次增长原来的一倍;
    最后:ArrayList只能用迭代器和for输出,而Vector能用迭代器、for和Enumberation输出
    什么是Iterator
    一些集合类提供了内容遍历的功能,通过java.util.Iterator接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用 Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合
    Iterator与ListIterator有什么区别?
    Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。
    在Hashtable上下文中同步是什么意思?
    同步意味着在一个时间点只能有一个线程可以修改哈希表,任何线程在执行hashtable的更新操作前需要获取对象锁,其他线程等待锁的释放。
    什么叫做快速失败特性
    从高级别层次来说快速失败是一个系统或软件对于其故障做出的响应。一个快速失败系统设计用来即时报告可能会导致失败的任何故障情况,它通常用来停止正常的操作而不是尝试继续做可能有缺陷的工作。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。如果一个iterator在集合对象上创建了,其它线程欲“结构化”的修改该集合对象,并发修改异常 (ConcurrentModificationException) 抛出。
    怎样使Hashmap同步?
    HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值