黑马程序员-集合框架

来源:互联网 发布:linux piwik安装详解 编辑:程序博客网 时间:2024/04/25 09:26
---------------------- ASP.Net+Android+IOS开发</a>、.Net培训、期待与您交流! ----------------------


集合框架

集合只用于存储对象,长度可变化

数组和集合类同是容器,有何不同?
数组即可存储对象,也可以存储基本数据类型,长度固定
集合只可以存储对象,长度可变

Collection
        |--List:该集合体系按照存入顺序存储,可以有重复元素
                |--Arraylist:数组
                |--LinkedList:链表
                |--Vector:数组
        |--Set:该集合体系没有索引,会按照特定的数据结构存放数据,并不是存入顺序存储,不允许重复元素
                |--HashSet:哈希表
                |--TreeSet:二叉树

ArrayList和Vector的区别:
Vector线程同步,效率低,现已被ArrayList替代
ArrayList线程不同步,效率要比Vector高

ArrayList和LinkedList的区别(动态数组和链表的区别):
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构
对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针
对于add和remove操作,LinkedList比较占优势,因为ArrayList要移动数据


Collection

Interface Collection是List、Set和Queue接口的父接口,提供了操作集合的基本方法

Method:
boolean add(E e)
void clear()    //清除集合中的所有元素
boolean contains(Object o)
boolean isEmpty()
Iterator iterator()    //返回一个Iterator对象,用于遍历集合里的元素
boolean remove(Object o)    //删除集合中指定元素
int size()    //返回元素个数
object[] toArray()    //集合转数组
<T> T[] toArray(T[] a)
boolean retainAll(Collection<?> c)    //取交集,放入当前集合中(调用方法的集合对象)


Iterator

Iterator对象被称为迭代器,用于迭代访问集合中的元素

Method:
boolean hasNext()
E next()
void remove()

import java.util.ArrayList;import java.util.Iterator;import java.util.Collection;/**迭代器*/class IteratorTest{    public static void main(String[] args)    {        Collection<String> c = new ArrayList<String>();        c.add("a1");        c.add("a2");        c.add("a3");        c.add("a4");        c.add("a5");        for(Iterator<String> it = c.iterator(); it.hasNext();)        {            String str = it.next();            System.out.println(str);            if("a1".equals(str))            {                it.remove();            }        }        System.out.println("--------------------");        System.out.println(c);    }}
集合在迭代过程中,不能被修改,否则会引发ConcurrentModificationException异常


List集合

List集合按照元素的存入顺序存入数据,且存在索引,因此List集合可以通过索引操作集合元素


boolean add(E e)
void add(int index, E element)
boolean addAll(Collection<? extends E>)

E remove(int index)

E set(int index, E element)

E get(int index)
int lastIndexOf(Object o)
List<E> subList(int fromIndex, int toIndex)    //注意此方法,对返回集合的操作就是对原集合的操作


ListIterator

List与Set集合都可以使用Iterator迭代器遍历元素,但List提供了一个更适用与List集合的ListIterator接口,用于迭代List集合,ListIterator接口继承了Iterator接口,提供了额外方法操作List集合

List接口的listIterator()方法返回ListIterator对象

boolean hasPervious()    //返回该迭代器关联的集合是否还有上一个元素
E previous()    //返回该迭代器的上一个元素
void add(E e)    //在指定位置插入一个元素
void set(E e)    //替换元素

ListIterator与普通Iterator进行对比:
ListIterator增加了向前迭代的功能(Iterator只能向后迭代)
ListIterator还可以添加、修改元素(Iterator只能删除元素)


ArrayList和Vector

ArrayList和Vector都是基于数组数据结构的List实现类,ArrayList和Vector内部封装了一个动态再分配的Object[]数组

ArrayList线程不安全,Collections工具类可以ArrayList集合变为线程安全
Vector线程安全,效率低

import java.util.*;/**ArrayList*/class ArrayListTest{    public static void main(String[] args)    {        ArrayList<String> al = new ArrayList<String>();        al.add("a1");        al.add("a3");        al.add("a2");        //正向迭代        for(ListIterator<String> li = al.listIterator(); li.hasNext(); )        {            System.out.println(li.next());        }        //指针如果在集合首位,反向迭代是找不到元素的        for(ListIterator<String> li = al.listIterator(); li.hasPrevious(); )        {            String str = li.previous();            if("a2".equals(str))            {                li.add("a4");            }            System.out.println(str);        }    }}

LinkedList

LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色

method:
void addFirst(E e)
void addLast(E e)
E getFirst(E e)    //如果集合为空,报异常
E getLast(E e)    //如果集合为空,报异常
E removeFirst(E e)    //如果集合为空,报异常
E removeLast(E e)    //如果集合为空,报异常
6.0新方法:
boolean offerFirst(E e)    //在头部添加元素
boolean offerLast(E e)    //在尾部添加元素
E peekFirst()    //返回第一个元素,如果集合为空,返回null
E peeklast()    //返回最后一个元素,如果集合为空,返回null
E poolFirst()    //移除第一个元素,如果集合为空,返回null
E poolLast()    //移除最后一个元素,如果集合为空,返回null


Set集合

Set集合没有索引,不允许重复元素,会按照数据结构存放数据

Set集合继承Collection的方法,没有提供任何额外的方法


HashSet

HashSet按Hash算法存储集合中的元素,Hash表有很好的存取和查找性能

HashSet具有以下特点:
1)不会保证元素的排列顺序,元素的位置据hashCode值而定
2)不同步
3)元素值可以是null

向HashSet存入一个元素的过程
当向HashSet集合中存入一个元素时,会先调用对象的hashCode()方法获取hashCode值,根据hashCode值来决定该对象在HashSet中的存储位置,如果hashCode值相同,再调用equals方法判断是否相同,如果equals方法返回false,说明不相同,可以存储,否则是相同元素,不可以存储

注意:
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,contatins方法会检索不到对象,也无法从HashSet集合中单独删除当前对象,从而造成内存泄漏


TreeSet

TreeSet默认会对元素进行自然排序(二叉树结构),也可以定制排序(关联比较器)

不允许存放相同元素,判断元素是否相同使用的自然排序或者比较器(如果存在)

自然排序
TreeSet会调用集合元素的compareTo(T o)方法来比较元素之间大小关系,将集合元素按升序排序,这种方式就是自然排序

Java提供了一个Comparable<T>接口,该接口里定义了一个int compareTo(T o)方法,一个类要实现自然排序,必须要实现该接口,覆写该方法
Java的一些常用类具备自然排序特征(即实现了Comparable接口),如String、Integer、Data、Time

import java.util.TreeSet;import java.util.Date;/**因为TreeSet默认会对元素进行比较,而只有相同类型的元素才有可比性所以TreeSet最好加上泛型,否则会因为类型不同报异常*/class TreeSetDemo{    public static void main(String[] args)    {        TreeSet ts = new TreeSet();        ts.add("sdf");        ts.add(new Date());    //运行时报ClassCastException异常        //如果使用泛型,上面的问题也就不存在了        TreeSet<String> ts2 = new TreeSet<String>();        ts2.add("adf");        ts2.add("fds");    }}
定制排序
TreeSet在创建对象时,可以关联一个比较器,优先使用比较器的比较方式

TreeSet<E>构造方法:TreeSet(Comparator<? super E> comparator)    //限定Comparator的泛型为E或者E的父类
import java.util.TreeSet;import java.util.Comparator;import java.util.Iterator;/**定制排序,创建TreeSet时传入一个比较器,并覆写compare方法*/class Person{    private int age;    public Person(int age)    {        this.age = age;    }    public int getAge()    {        return age;    }}class TreeSetTest2{    public static void main(String[] args)    {        //TreeSet关联一个比较器,并覆写比较器中的compare方法        TreeSet<Person> ts = new TreeSet<Person>(new Comparator<Person>()        {            @Override            public int compare(Person p1, Person p2)            {                //使用了Integer本来具有的比较特性(Integer实现Comparable接口,并覆写了compareTo方法,且该方法是升序排序)                return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));            }        });        //在添加元素的过程中,已经使用传入的比较器完成了比较        ts.add(new Person(5));        ts.add(new Person(6));        ts.add(new Person(4));        //顺序输出TreeSet中每个人的年龄        for(Iterator<Person> it = ts.iterator(); it.hasNext();)        {            System.out.println(it.next().getAge());        }    }}

Map集合

Map用于保存具有映射关系的数据,一组key、一组value

如果存入的key相同,后面的会覆盖前面的,所以Map集合中不存在相同的key

Method:
V put(K key, V value)    //如果key相同,后添加的会覆盖原来的键值对,并返回原来键值对的value,如果原来不存在此key的键值对,则返回null
void putAll(Map<? extends K, ? extends V> m)

void clear()    //删除该Map对象中所有key-value对
V remove(Object key)    //删除指定key所对应的key-value对

boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()

V get(Object key)    //根据key,获取对应的value
int size()
Collection<V> values()    //返回该Map里所有value组成的Collection
Set<K> keySet()    //返回该Map中所有key所组成的Set集合

Set<Map.Entry<K, V>> entrySet()    //返回Map中所包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry(Entry是Map的内部接口)对象


HashMap与Hashtable

HashMap:底层是哈希表数据结构,允许使用null键null值。线程不同步,效率高。jdk1.2
Hashtable:底层是哈希表数据结构,不可以存入null键null值。线程同步,效率底。jdk1.0

key不允许重复,哈希结构判断相同使用的是hashcode()和equals(Object)方法,所以作为key的元素要覆写这两个方法
import java.util.HashMap;import java.util.Set;import java.util.Iterator;import java.util.Map;/**定义学生类,有姓名、年龄两个属性HashMap中key为学生对象,value为住址address注意:姓名和年龄相同的视为同一个学生,保证学生的唯一性*///二叉树数据结构需要自然排序,哈希表使用hashCode()和equals()方法//此学生类对象即可以存入二叉树数据结构,也需要存入哈希表中class Student implements Comparable<Student>{    private String name;    private int age;    Student(String name, int age)    {        this.name = name;        this.age = age;    }    public String getName()    {        return name;    }    public int getAge()    {        return age;    }    @Override    public String toString()    {        return name+"---"+age;    }    //哈希表数据结构判断元素是否相同使用的方法    @Override    public int hashCode()    {        return name.hashCode() + age*15;    }    //哈希表数据结构判断元素是否相同使用的方法    @Override    public boolean equals(Object obj)    {        if(!(obj instanceof Student))        {            throw new ClassCastException("不是Student类型");        }        Student stu = (Student)obj;        return name.equals(stu.getName()) && age==stu.getAge();    }    //二叉树数据结构默认使用的比较依据    @Override    public int compareTo(Student stu)    {        int num = name.compareTo(stu.getName());        if(num == 0)        {            num = new Integer(age).compareTo(new Integer(stu.getAge()));        }        return num;    }}class HashMapTest{    public static void main(String[] args)    {        HashMap<Student, String> hs = new HashMap<Student, String>();        hs.put(new Student("zhangsan", 17), "beijing");        //姓名、年龄相同视为同一个学生        hs.put(new Student("zhangsan", 17), "shanghai");        hs.put(new Student("lisi", 17), "shanghai");        hs.put(new Student("wangwu", 17), "nanjing");        hs.put(new Student("zhaoliu", 17), "tianjin");        //获取所有key到Set集合中        Set<Student> keySet = hs.keySet();        for(Iterator<Student> it = keySet.iterator(); it.hasNext(); )        {            Student stu = it.next();            //根据key获取value            String address = hs.get(stu);            System.out.println(stu.getName()+"---"+address);        }        //另外一种输出HashMap集合中元素的方法        System.out.println("-----------------------------------");        Set<Map.Entry<Student, String>> entrySet = hs.entrySet();        for(Map.Entry<Student, String> ele : entrySet)        {            System.out.println(ele.getKey() + "---" + ele.getValue());        }    }}

TreeMap

使用了二叉树数据结构,默认会对key自然排序,也可以在创建TreeMap实例时传入比较器

不允许存在相同key,判断元素是否相同使用的是自然排序或者比较器
import java.util.*;/**获取字符串中各个字母出现的次数输出格式:a(个数)b(个数)...*/class TreeMapTest{    public static void main(String[] args)    {        String str = method_1("adflkjld,.,.,flksajdf");        System.out.println(str);    }    public static String method_1(String str)    {        char[] chr = str.toCharArray();        TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();        for(int i = 0; i < chr.length; i++)        {            //如果不是字母就跳过            if(!((chr[i] >= 'a' && chr[i] <= 'z') || (chr[i] >= 'A' && chr[i] <= 'Z')))                continue;            Integer count = tm.get(chr[i]);            if(count == null)                tm.put(chr[i], 1);            else                tm.put(chr[i], ++count);        }        StringBuilder sb = new StringBuilder();        Set<Map.Entry<Character, Integer>> entrySet = tm.entrySet();        for(Iterator<Map.Entry<Character, Integer>> it = entrySet.iterator(); it.hasNext(); )        {            Map.Entry mapEntry = it.next();            sb.append(mapEntry.getKey()+"("+mapEntry.getValue()+")");        }        return sb.toString();    }}

Collections工具类

数组提供了Arrays工具类,包含的全部是静态方法
集合提供了Collections工具类,包含的全部是静态方法

Collections,提供了一些方法对集合元素进行排序、查询和修改、实现同步等

排序操作
static <T extends Comparable<? super T>> void sort(List<T> list)    //对List中元素进行自然排序(前提是元素有排序性)
static <T> void sort(List<T> list, Comparator<? super T> c)    //使用比较器对List中元素进行排序
static void reverse(List<?> list)    //反转指定List集合中元素的顺序
static void shuffle(List<?> list)    //对List集合元素进行随机排序(模拟洗牌动作)
static <T> Comparator<T> reverseOrder()    //反转自然顺序
static <T> Comparator<T> reverseOrder(Comparator<T> cmp)    //反转比较器cmp的顺序
class ReverseOrderTest{    public static void main(String[] args)    {        //反转自然顺序        //TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());        //反转比较器的顺序        TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new Com()));        ts.add("asdlkf");        ts.add("fsdl");        ts.add("dsdkf");        ts.add("kf");        ts.add("bf");        ts.add("af");        System.out.println(ts);    }}//定义一个比较器class Com implements Comparator<String>{    @Override    public int compare(String st1, String st2)    {        int num =st1.length()-st2.length();        if(num == 0)        {            return st1.compareTo(st2);        }        return num;    }}
查找、替换操作
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)    //返回最大值(前提是可自然排序)
static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)    //使用二分搜索法,在list中搜索key,并返回索引,必须保证List处于有序状态
static void fill(List<? super T> list, T obj)    //使用指定元素obj替换指定List集合中的所有元素
static <T> boolean replaceAll(List<T> list, T oldVal, T new Val)
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());}

数组与集合的相互转换

数组转集合,Arrays提供如下方法:
static <T> List<T> asList(T... a)

注意:如果数组中存储的基本数据类型,asList会将数组整体作为一个元素存入集合

集合转数组,Collection提供如下两个方法:
Object[] toArray()
<T> T[] toArray(T[] a)




---------------------- ASP.Net+Android+IOS开发</a>、.Net培训、期待与您交流! ----------------------
原创粉丝点击