Java集合框架

来源:互联网 发布:普通话翻译闽南话软件 编辑:程序博客网 时间:2024/06/15 17:03

一、Java集合类综述

Java集合类(位于java.util包中)主要有两个接口CollectionMap派生出来,大致分为Set、List、Queue、Map四种体系。

集合类框架图

注意:集合中只可以保存对象,不可以保存基本数据类型。
二、Collection
1. Collection和Iterator接口
1.1 Collection中的方法
boolean add(Object o):向集合中添加一个元素。
boolean addAll(Collection c):把集合c中所有元素添加到指定集合中。
void clear():清除集合中所有元素。
boolean remove(Object o):删除集合中指定元素o。
int size():返回集合中元素个数。
boolean contains(Object o):返回集合中是否包含指定元素o。
boolean containsAll(Collection c):返回集合中是否包含集合c中的所有元素。
boolean isEmpty():判断集合是否为空。
boolean retainAll(Collection c):返回两个集合是否有交集。
Object[] toArray():把集合转化为数组。
Iterator iterator():返回一个Iterator对象,用于遍历集合中的元素。
1.2 Iterator遍历数组
迭代器:集合取出元素的方式。
取出方式定义在集合内部,可以直接访问集合中的元素。
Collection接口extends了Iterable接口,Iterable接口提供了iterator()方法获取Iterator类型对象,来遍历集合。
Iterator接口方法:
boolean hasNext():判断被迭代的集合中是否还有下一个元素。
Object next():返回集合中的下一个元素。
void remove():删除集合中上一次next方法返回的元素(直接修改了集合)。

代码实现:

ArrayList al=new ArrayList();al.add("java01");al.add("java02");al.add("java03");Iterator it=al.iterator();while(it.hasNext()){    System.out.println(it.next());}

2.List
2.1 List介绍
元素是有序的,元素可以重复。因为该集合类有索引

List接口框架图
2.2 List特有方法
增:
add(int index , Object element)
addAll(int index , Collection c)
删:
remove(int index)
改:
set(int index,Object element)
查:
get(int index)
subList(int from , int to)
listIterator()
获取位置:
indexOf(Object obj)
lastIndexOf(Object obj)
……………………………..可爱的分割线………………………………………..
List集合类中特有的迭代器:ListIterator
ListIterator时Iterator的子接口,与Iterator相比,另外实现了增加、修改、反向遍历功能。

代码实现:

ArrayList<String> arrayList=new ArrayList<String>();arrayList.add("zhao");arrayList.add("gao");arrayList.add("qiao");ListIterator<String> li=arrayList.listIterator();   System.out.println("正向遍历:");while(li.hasNext()){    //获取某个元素的值    Object obj=li.next();    System.out.println(obj);    if(obj.equals("qiao")){        //修改某个元素值        li.set("zhu");    }else if(obj.equals("gao")){        //删除某个元素        li.remove();    }       //增加某个元素    li.add("duan");}System.out.println("逆向遍历:");while(li.hasPrevious()){    Object obj=li.previous();    System.out.println(obj);}

2.3 ArrayList
底层的数据结构为数组结构。线程不同步。’

去除Arraylist集合对象中重复元素的代码实现:

import java.util.ArrayList;import java.util.Iterator;class Person{    private String name;    private int age;    Person(String name,int age){        this.name=name;        this.age=age;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    //实现部分(判断元素是否相同使用的是equals()方法)    public boolean equals(Object obj){        if(!(obj instanceof Person))            return false;        else{            Person p=(Person)obj;            return this.name.equals(p.name) && this.age==p.age;        }    }}public class ArrayListTest {    public static void main(String[] args) {        ArrayList<Person> al=new ArrayList<Person>();        al.add(new Person("zsw", 23));        al.add(new Person("gnf", 24));        al.add(new Person("gzb", 25));        al.add(new Person("lxg", 26));        al.add(new Person("gzb", 25));        al=singleElement(al);        Iterator<Person> li=al.iterator();        while(li.hasNext()){            Person p=li.next();            System.out.println(p.getName()+"....."+p.getAge());        }    }    public static ArrayList<Person> singleElement(ArrayList<Person> al){        ArrayList<Person> newAl=new ArrayList<Person>();        Iterator<Person> li=al.iterator();        while(li.hasNext()){            Object obj=li.next();            if(!newAl.contains(obj)){                newAl.add((Person)obj);            }        }        return newAl;    }}

2.4 LinkedList
底层的数据结构是链表结构。
同时实现了Deque接口,既可以当做也可以当做队列使用。

使用LinkedList模拟队列的代码实现:

import java.util.LinkedList;class Duilie{    private LinkedList<String> ll;    Duilie(){        ll=new LinkedList<String>();    }    public void add(String str){        ll.addFirst(str);    }    public String get(){        return ll.removeLast();    }    public boolean isEmpty(){        return ll.isEmpty();    }}public class LinkedListTest {    public static void main(String[] args) {        Duilie d=new Duilie();        d.add("aa");        d.add("bb");        d.add("cc");        d.add("dd");        while(!d.isEmpty()){            System.out.println(d.get());        }       }}

2.5 Vector
底层数据结构是数组结构。线程同步。
枚举时Vector中特有的取出方式。
代码实现:

Vector<Integer> v=new Vector<Integer>();v.add(new Integer(11));v.add(new Integer(12));v.add(new Integer(13));Enumeration<Integer> e=v.elements();while(e.hasMoreElements()){    System.out.println(e.nextElement());}

2.6 Stack
Vector的子类。
表示后进先出(LIFO)的对象堆栈。
方法:
push(Object obj):入栈。
pop():出栈。
peek():取栈顶元素。
empty():测试堆栈是否为空。
search(Object obj):返回对象在堆栈中位置。

2.7 List实现类性能分析
数组作为底层的ArrayList在随机访问时效率高。
链表作为底层的LinkedList插入、删除操作时效率高。
③遍历List集合元素,对于ArrayList、Vector使用随机访问方法(get)来遍历;对于LinkedList使用迭代器(Iterator)来遍历。
④多个线程同时访问List中元素,考虑使用Collections工具类将集合包装成线程安全的集合。

3.Set
3.1 Set介绍
元素是无序的,元素不可以重复

Set集合框架

3.2 HashSet
底层数据结构是哈希表,线程是非同步的。
HashSet是如何保证元素唯一的??
通过两个方法:hashCode()和equals(Object obj)
如果两个元素的hashCode()值相同,才会判断equals(Object obj)是否为true;
如果两个元素的hashCode()值不同,不会调用equals(Object obj)。

HashSet复写hashCode()和equals(Object obj)的代码实现:

import java.util.HashSet;import java.util.Iterator;class Person{    private int age;    private String name;    Person(String name,int age){        this.name=name;        this.age=age;    }    public int getAge() {        return age;    }    public String getName() {        return name;    }    public int hashCode(){//复写hashCode()方法        return this.name.hashCode()+age*19;    }    public boolean equals(Object obj){//复写equals()方法        if(!(obj instanceof Person))            return false;        else{            Person p=(Person)obj;            System.out.println(this.name+"."+p.name);            return p.name.equals(this.name)&&p.age==this.age;        }    }}public class HashSetTest {    public static void main(String[] args) {        HashSet<Person> hs=new HashSet<Person>();        hs.add(new Person("zsw", 23));        hs.add(new Person("zsw", 23));        hs.add(new Person("gzb", 26));        hs.add(new Person("cya", 18));          Iterator<Person> it=hs.iterator();        while(it.hasNext()){            Person p=it.next();            System.out.println(p.getAge()+"......"+p.getName());        }    }}

重写hashCode()一般方法:
①把对象中每一个实例变量计算出一个int类型的hashCode值。

变量类型计算方式变量类型计算方式booleanhashCode=(f?0:1);floathashCode=Float.floatToIntBits(f);整形(byte,short,char,int)hashCode=(int)f;doublelong l=DoubleToLongBits(f);
hashCode=int(l^(l>>>32));longhashCode=(int)(f^(f>>>32)); 引用类型hashCode=f.hashCode();

②各个实例变量的hashCode值乘以一个质数后相加。
例:f1.hashCode()*31+int(f2)*19;

3.3 TreeSet
底层数据结构是二叉树,线程是非同步的。
可以对集合中的元素进行排序:
方法1:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo()方法。这种方法称为元素的自然排序
方法2:让集合自身具备比较性。
定义了比较器,将比较器作为参数传给TreeSet集合的构造函数。
定义一个类,实现Comparator接口,覆盖compare()方法。

代码实现:

import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;//第一种方法:实现Comparable接口class People implements Comparable{    private int age;    private String name;    public People(int age, String name) {        this.age = age;        this.name = name;    }    public int getAge() {        return age;    }    public String getName() {        return name;    }       public int compareTo(Object obj){        if(!(obj instanceof People))            throw new RuntimeException("不是人物类型对象");        else{            People p=(People)obj;            if(this.age>p.age)                return 1;            else if(this.age==p.age)                return this.name.compareTo(p.name);            else {                return -1;            }        }    }}//第二种方法:定义一个比较器实现Comparator接口class MyCompare implements Comparator{    public int compare(Object obj1,Object obj2){        People p1=(People)obj1;        People p2=(People)obj2;        int num=new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));        if(num==0)            return p1.getName().compareTo(p2.getName());        return num;    }}public class TreeSetTest {    public static void main(String[] args){        TreeSet<People> ts=new TreeSet<People>(new MyCompare());        ts.add(new People(17,"zsw"));        ts.add(new People(14, "gzb"));        ts.add(new People(19, "cya"));        ts.add(new People(17, "zln"));        ts.add(new People(22, "qyf"));        Iterator<People> it=ts.iterator();        while(it.hasNext()){            People p=it.next();            System.out.println("main:"+p.getAge()+"....."+p.getName());        }    }}

注意:当两种排序都存在时,以比较器为主。
3.4 LinkedHashSet
线程非同步。
与HashSet相同,也是根据元素的hashCode()值确定元素位置;同时使用链表维护元素次序。
遍历时,会按照元素的添加顺序来访问集合中元素。

代码实现:

package com.zsw.set;import java.util.LinkedHashSet;public class LinkedHashSetTest {    public static void main(String[] args){        LinkedHashSet<String> lhs=new LinkedHashSet<>();        lhs.add("zsw");        lhs.add("gzb");        lhs.add("qyf");        System.out.println(lhs);//输出[zsw,gzb,qyg]        lhs.remove("gzb");//移除一个元素        lhs.add("lxg");//插入一个新元素        System.out.println(lhs);//输出[zsw,qyf,lxg]    }}

3.5 EnumSet
专门为枚举类设计的集合类,线程非同步。
集合元素有序,EnumSet以枚举值在Enum类中的定义顺序来决定集合元素的顺序。
不允许加入null元素。

代码实现

package com.zsw.set;import java.util.Collection;import java.util.EnumSet;import java.util.HashSet;enum Season{    SPRING,SUMMER,FALL,WINTER}public class EnumSetTest {    public static void main(String[] args) {        //allOf()函数创建包含指定枚举类所有枚举值的集合        EnumSet es1=EnumSet.allOf(Season.class);        //noneOf()函数创建一个指定枚举类的空集合        EnumSet es2=EnumSet.noneOf(Season.class);        //of()函数创建包含一个或者多个枚举值的EnumSet集合        EnumSet es3=EnumSet.of(Season.SUMMER,Season.WINTER);        //range(E from,E to)函数创建从from到to范围内所有枚举值的EnumSet集合        EnumSet es4=EnumSet.range(Season.SUMMER, Season.WINTER);        //complementOf(EnumSet s)返回s集合中所没有的枚举值的集合        EnumSet es5=EnumSet.complementOf(es4);        Collection c=new HashSet();        c.add(Season.SPRING);        c.add(Season.FALL);        //copyOf(Collection c)函数使用普通集合(集合中所有元素必须属于同一枚举类)创建EnumSet集合()        EnumSet es6=EnumSet.copyOf(c);    }}

3.6 Set实现类性能分析
①HashSet性能总比TreeSet好;因为TreeSet总需要额外的红黑树(二叉树)算法维护元素次序。
②当需要保持排序时,使用TreeSet.
③LinkedHashSet比HashSet稍微慢一点,因为链表维护的开销。
④EnumSet是Set实现类里性能最好的。
4.Queue
4.1 Queue介绍
Queue用于模拟“队列”,队列指”先进先出”(FIFO)的容器。
Queue
常见方法:
void add(Object e):将指定元素加入队列尾部
Object element():获取队列头部元素但不删除
boolean offer(Object e):将指定元素加入队列尾部。对于有容量限制队列效果好。
Object peek():获取队列头部元素但不删除。
Object poll():获取队列头部元素并删除。
Object remove():获取队列头部元素并删除。

4.2 PriorityQueue
PriorityQueue实现类保持队列元素的顺序按照队列元素的大小排序。
排序方法有两种:
自然排序:集合元素实现Comparable接口。
定制排序:队列传入Comparator比较器对象。
TreeSet排序要求基本一致。

代码实现:

package com.zsw.queue;import java.util.PriorityQueue;public class PriorityQueueTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        PriorityQueue pq=new PriorityQueue();        pq.offer(6);        pq.offer(3);        pq.offer(-1);        pq.offer(12);        //依次输出-1,3,6,12        System.out.println(pq.poll());        System.out.println(pq.poll());        System.out.println(pq.poll());        System.out.println(pq.poll());    }}

4.3 Deque接口
代表一个双端队列,允许从两端操作队列的元素。
可以当做双端队列,也可以当做(推荐使用)使用。

4.4 ArrayDeque
Deque接口的实现类,底层数据结构是数组

ArrayDeque作为”栈”代码展示:

package com.zsw.queue;import java.util.ArrayDeque;public class ArrayDequeTest {    public static void main(String[] args) {        ArrayDeque stack=new ArrayDeque();        stack.push("zsw");        stack.push("lxg");        stack.push("gzb");        stack.push("wrg");        System.out.println(stack.pop());        System.out.println(stack.pop());        System.out.println(stack.pop());        System.out.println(stack.pop());    }}

三、Map

1. Map介绍
map

基本方法:
Object put(Object key,Object value):添加一个键值对。
void putAll(Map m):复制指定Map中的键值对。
boolean containsKey(Object key):判断集合中是否包含指定key。
boolean containsValue(Object value):判断集合中是否包含指定value。
Object get(Object key):返回指定key对应的value值。
Object remove(Object key):删除指定key所对应的键值对。
void clear():删除所有键值对。
Set keySet():返回Map集合中所有key组成的Set集合。
Set entrySet():返回Map集合中所有key-value组成的Set集合。
Collection values():返回Map集合中所有value组成的Collection。
int size():返回Map集合的键值对个数。
2. Map集合的取出方式

2.1 keySet()
将Map中所有键存入Set集合;Set集合迭代器迭代取出所有key,使用get(Object key)方法取出value。

代码实现

package com.zsw.quchu;import java.util.HashMap;import java.util.Iterator;import java.util.Set;public class keySetTest {    public static void main(String[] args){        HashMap<String, String> hm=new HashMap<>();        hm.put("zsw", "23");        hm.put("lxg", "24");        hm.put("gzb", "25");        Set<String> s=hm.keySet();        Iterator<String> it=s.iterator();        while(it.hasNext()){            String name=it.next();            String age=hm.get(name);            System.out.println(name+"....."+age);        }    }}

2.2 entrySet
将Map集合的映射关系存储到Set集合,Set集合的数据类型是Map.Entry;使用Map.Entry的getKey()和getValue()方法获取key和value。

代码实现

package com.zsw.quchu;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;public class entrySetTest {    public static void main(String[] args){        HashMap<String, Integer> hm=new HashMap<>();        hm.put("zsw", 23);        hm.put("gzb", 25);        hm.put("qyf", 24);        hm.put("xxx", 12);        Set<Map.Entry<String,Integer>> s=hm.entrySet();        Iterator<Map.Entry<String, Integer>> it=s.iterator();        while(it.hasNext()){            Map.Entry<String, Integer> me=it.next();            System.out.println(me.getKey()+"..."+me.getValue());        }    }}

3. Map实现类

3.1 Hashtable
底层数据结构式哈希表,无序,线程同步。
key和value都不可以为null。

代码实现

package com.zsw.hashtable;import java.util.Hashtable;public class HashtableTest {    public static void main(String[] args) {        Hashtable ht=new Hashtable();        ht.put("zsw", "201511899");        ht.put("qyf", "201411777");        //key和value都不可以为null        //ht.put(null, null);        ht.put("lxg", "201411666");        System.out.println(ht);    }}

3.2 Properties
Hashtable的子类。
键值都是字符串。通常用来处理属性文件

代码实现

package com.zsw.hashtable;import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.Properties;public class PropertiesTest {    public static void main(String[] args)throws Exception {        Properties prop=new Properties();        //load()从文件中加载键值对        prop.load(new FileInputStream("info.ini"));        //getProperty()获取指定属性值        System.out.println(prop.getProperty("zsw"));        //setProperty()设置键值对        prop.setProperty("gzb", "201311888");        //store()输出到指定文件        prop.store(new FileOutputStream("info.ini"), "my comment");        //list()列出属性值列表        prop.list(System.out);    }}

3.3 HashMap
底层数据结构是哈希表 ,无序,线程不同步。
key和value可以为null。
对于HashMap和Hashtable:
①用作key的对象必须实现hashCode()和equals()方法。
②判断两个value值相等的标准:equals()函数返回true。

3.4 LinkedHashMap
是HashMap的子类。
使用双向链表维护键值对的次序;迭代顺序与插入顺序一致。

代码实现

package com.zsw.hashmap;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Set;public class LinkedHashMapTest {    public static void main(String[] args) {        LinkedHashMap<String, Integer> lhm=new LinkedHashMap<>();        lhm.put("zsw", 23);        lhm.put("qyf", 24);        lhm.put("lxg", 25);        lhm.put("zln", 24);        Set<String> s=lhm.keySet();        Iterator<String> it=s.iterator();        while(it.hasNext()){            String name=it.next();            System.out.println(name+"..."+lhm.get(name));        }    }}

3.5 TreeSet
底层数据结构是二叉树(红黑树),有序,线程不同步。
两种排序方式:
与TreeSet两种排序方式类似。

代码实现

package com.zsw.treeset;import java.util.*;//定制排序class StuNameComparator implements Comparator<Student>{    public int compare(Student s1,Student s2)    {        int num=s1.getName().compareTo(s2.getName());        if(num==0)            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));        return num;    }}//自然排序class Student implements Comparable<Student>{    private String name;    private int age;    Student(String name,int age)    {        this.name = name;        this.age = age;    }    public int compareTo(Student s)    {        int num = new Integer(this.age).compareTo(new Integer(s.age));        if(num==0)            return this.name.compareTo(s.name);        return num;    }    public int hashCode()    {        return name.hashCode()+age*31;    }    public boolean equals(Object obj)    {        if(!(obj instanceof Student))            throw new ClassCastException("类型不匹配");        Student s = (Student)obj;        return this.name.equals(s.name) && this.age==s.age;    }}class  TreeSetTest{    public static void main(String[] args)     {        TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());        tm.put(new Student("alisi0",21),"beijing");        tm.put(new Student("dlisi6",22),"shanghai");        tm.put(new Student("blisi5",23),"nanjing");        tm.put(new Student("elisi4",24),"wuhan");        Set<Map.Entry<Student,String>> entrySet = tm.entrySet();        Iterator<Map.Entry<Student,String>> iter = entrySet.iterator();        while(iter.hasNext())        {            Map.Entry<Student,String> me = iter.next();            Student stu = me.getKey();            String addr = me.getValue();            System.out.println(stu+"......"+addr);        }    }}

3.6 WeakHashMap
WeakHashMap中每个key对象只持有对实际对象的弱引用,因此,当垃圾回收了该keys所对应的实际对象后,WeakHashMap会自动删除该key对应的键值对。

代码展示

package com.zsw.weakhashmap;import java.util.WeakHashMap;public class WeakHashMapTest {    public static void main(String[] args) {        WeakHashMap<String, String> whm=new WeakHashMap<>();        //两个key都是匿名字符串对象(没有其他引用)        whm.put(new String("China"), new String("Chinese"));        whm.put(new String("Japan"), new String("Japanese"));        //字符串对象        whm.put("America", "English");        //垃圾回收        System.gc();        System.runFinalization();        //只会输出{America=English}        System.out.println(whm);    }}

3.7 IdentityHashMap
实现机制与HashMap类似。
key和value允许为null。
当且仅当两个key严格相等时(key1==key2),才可以认为两个key相等。

代码实现

package com.zsw.identityhashmap;import java.util.IdentityHashMap;public class IdentityHashMapTest {    public static void main(String[] args) {        IdentityHashMap<String, Integer> ihm=new IdentityHashMap<>();        //这两个key不满足严格相等        ihm.put(new String("math"), 89);        ihm.put(new String("math"), 98);        //字符串常量在常量池只有一份,满足严格相等        ihm.put("java", 93);        ihm.put("java", 66);        //输出{math=89, java=66, math=98}        System.out.println(ihm);    }}

3.8 EnumMap
所有key都必须是单个枚举类的枚举值。
内部以数组形式保存。
按照key自然顺序(枚举类中顺序)维护key-value顺序。
key不允许为null,value允许为null。

代码实现

package com.zsw.enummap;import java.util.EnumMap;import java.util.EnumSet;enum Season{    SPRING,SUMMER,FALL,WINTER}public class EnumMapTest {    public static void main(String[] args) {        EnumMap<Season, String> em=new EnumMap<>(Season.class);        em.put(Season.SPRING, "chuntian");        em.put(Season.WINTER, "dongtian");        em.put(Season.SUMMER, "xiatian");        //自然顺序输出{SPRING=chuntian, SUMMER=xiatian, WINTER=dongtian}        System.out.println(em);    }}

3.8 性能分析
①Hashtable和HashMap比TreeSet要,因为TreeSet使用红黑树。
②TreeSet的好处是有序
③LinkedHashMap比HashMap慢一点,因为它需要链表保持键值对添加顺序
③EnumSet性能最好
四、Collections工具类
1.介绍
操作Set、List、Map等集合的工具类,都是静态方法
2.排序
void reverse(List list):反转list集合中元素顺序。
void shuffle(List list):对list集合中元素随机排序。
void sort(List list):对list集合元素按照升序排序。
void sort(List list,Comparator c):根据比较器顺序对集合排序。
void swap(List list,int,int j):对list集合中i处和j处元素互换。
void rotate(List list,int distance):当distance为正数时,将list集合的后distance个元素移到前面;当distance为负数时,将list集合前distance个元素移到后面。
3. 查找替换
int binarySearch(List list,Object key):二分法搜索list集合中key的位置,必须list处于有序状态。
Object max(Collection coll):根据自然顺序返回最大元素。
Object min(Collection coll):根据自然顺序返回最小元素。
Object max(Collection coll,Comparator comp):按照比较器指定顺序返回最大元素。
Object min(Collection coll,Comparator comp):按照比较器指定顺序返回最大元素。
void fill(List list,Object obj):使用obj替换list中所有元素。
int frequenc(Collection coll,Object o):返回指定集合中指定元素出现次数。
boolean replaceAll(List list,Object new,Object old):使用新值替换指定集合所有旧值。
4.同步控制
Collections提供了了多个synchronizedXxx()方法,解决多线程并发访问的线程安全问题。

代码实现:

package com.zsw.collections;import java.util.*;public class CollectionsTest {    public static void main(String[] args) {        Collection c=Collections.synchronizedCollection(new ArrayList());        List list=Collections.synchronizedList(new ArrayList());        Set s=Collections.synchronizedSet(new HashSet());        Map m=Collections.synchronizedMap(new HashMap());    }}

********************************end************************************

0 0