集合
Collections
◆所以的集合类都实现了collection接口。
ArrayList
◆集合中存放的是对象的引用而不是对象本身。
◆ArrayList是一个动态增长的数组,当我们调用无参构造函数时,默认会分配一个长度为10的数组,当空间不足时会动态增长为原来的1.5倍加1,然后将旧的数组复制到新的数组当中,当新的数组无法容纳更多的元素时,重复该过程。
◆可以用ArrayList(int initialCapacity)来初始化数组的容量,容量过大时,可以用trimToSize()方法挤压到刚好适合的大小,也可以用ensureCapacity(int minCapacity)来调整大小。
◆ArrayList是一个List接口的可变数组的实现,实现了List接口里面的所有方法,并且允许它的所有成员为null。它可以粗略的认为和Vector相当,但ArrayList不是同步的,Vector是同步的。
◆ArrayList底层维护的是一个
| Private
  transient object[]
  elementData | 
常用的方法
| package com.anllin.collections; import java.util.ArrayList; public class ArrayListTest {     public static void main(String[] args)     {        // 当这样初始化时,会产生一个容量 为10的类型为Object[]的elementData数组。ArrayList的内部实现方式。        // 当容量超过10时,会自动增长为(10*3)/2+1        ArrayList list = new ArrayList();        list.add("Hello");        list.add("World");        list.add("Welcome");        for (int i = 0; i < list.size(); i++)        {            System.out.println(list.get(i));        }        list.remove("Welcome");        list.add("World");        list.add("aaa");        list.add("bbb");        for (int i = 0; i < list.size(); i++)        {            System.out.println(list.get(i));        }        System.out.println(list.indexOf("World"));        System.out.println(list.indexOf("aaa"));        list.clear();        System.out.println(list.size());     } } | 
◆对于ArrayList来说,当你没有使用泛型时,默认里面的成员类型都为Object类型,当你把int,String等类型放进去后,取出来时要进行相应的类型转化,否则程序运行时会报错。
| package com.anllin.collections; import java.util.ArrayList; public class
  ArrayListTest3 {     public static void main(String[] args)     {        ArrayList list = new ArrayList();                list.add("anllin");        list.add(new
  Integer(23));        list.add(new Boolean(false));        list.add(new
  Long(1379446));                for (int i = 0; i < list.size(); i++)        {            System.out.println(list.get(i));        }                int age =
  ((Integer)list.get(1)).intValue();        System.out.println(age);     } } | 
◆     对于原生数据类型,不能直接把它添加到ArrayList中,要使用相应的包装类,使用泛型则可以避免这种问题。当调用toArray方法时,也不能直接用原生数据类型的包装类型进行转化,因为数组时存放的是对象,可能存的是不同的包装类型。如下:
| package com.anllin.collections; import java.util.ArrayList; public class ArrayListTest4 {     public static void main(String[] args)     {        ArrayList list = new ArrayList();                list.add(new Integer(1));        list.add(new Integer(2));        list.add(new Integer(3));        list.add(new Integer(4));        list.add(new Integer(5));        list.add(new Integer(6));        list.add(new Integer(7));                int sum = 0;        for (int i = 0; i < list.size(); i++)        {            int val = ((Integer)list.get(i)).intValue();            sum += val;        }        System.out.println(sum);                //不能直接用Integer[] 转换,因为list.toArray()产生的是一个Object[],数组里的每个元素不一定是Integer类型的。        Object[] arr = list.toArray();                for (int i = 0; i < arr.length; i++)        {            int val = ((Integer)arr[i]).intValue();            System.out.println(val);        }     } } | 
◆如果你在集合中存放了自定义的类,那么打印时会调用Object.toString()方法,如果你想要打印自己想要的结果,就要重写toString()方法。
| package com.anllin.collections; import java.util.ArrayList; public class ArrayListTest2 {     public static void main(String[] args)     {        ArrayList list = new ArrayList();                list.add(new Point(1,1));        list.add(new Point(2,2));        list.add(new Point(3,3));        list.add(new Point(4,4));                //自定义的类要输入自己想要的格式信息,必须重写toString()方法        System.out.println(list);     } } class Point {     /**      *
  Properties      */     int x;     int y;          /**      *
  Constructor      * @param x      * @param y      */     public Point(int x,int y)     {        this.x = x;        this.y = y;     }          /**      * @category Method
  ref Object.toString() is overrided.      */     public String toString()     {        return "x = " + this.x + ", y = " + this.y;     } } | 
◆对于ArrayList的删除操作,需要将后续的元素往前移动,代价比较高。
◆如果要经常对元素进行查找,用ArrayList比较好,如果要经常对元素插入或删除,用LinkedList比较好。
LinkedList
◆     LinkedList也实现了List接口,所以操作上和ArrayList相似,不同的是,它也实现了deque,queue接口,提供了get,insert,remove的其他一些细粒度的操作,我们可以用这些方法轻松的实现stack,queue和double-ended queue。
◆     底层维护的是一个双链表,双链表中维护的是一个个Entry<E>结点类。
| private static class Entry<E> {     E
  element;     Entry<E> next;     Entry<E> previous;     Entry(E element, Entry<E> next, Entry<E> previous) {         this.element = element;         this.next = next;         this.previous = previous;     } } | 
基本的操作:
| public class LinkedListTest {     public static void main(String[] args)     {        LinkedList list = new LinkedList();                list.add("aaa");        list.add("bbb");        list.add("ccc");        list.add("ddd");                for(Iterator iterator = list.iterator();
  iterator.hasNext();)        {            System.out.println(iterator.next());        }     } } | 
◆单链表结点类
| public class Node {     Node next;     String data;          public Node(String data)     {        this.data = data;     }          public String toString()     {        return this.data.toString();     } } | 
◆单链表的一些基本操作
| public class NodeTest {     public static void main(String[] args)     {        Node node1 = new Node("node1");        Node node2 = new Node("node2");                Node node3 = new Node("node3");                //add nodes generate a cycle single Liked List.        node1.next = node2;        node2.next = node3;        node3.next = node1;                System.out.println(node1.next.next);        System.out.println("----------------");                Node node4 = new Node("node4");                //insert node4 into between node1 and node 2;        node1.next = node4;        node4.next = node2;                System.out.println(node1.next.next);        System.out.println("----------------");                //remove the node4        node1.next = node2;        node4.next = null;        System.out.println(node1.next.next);        System.out.println("----------------");     } } | 
◆双链表结点类
| public class DbNode {     DbNode next;     String data;     DbNode priv;          public DbNode(String data)     {        this.data = data;     }          public String toString()     {        return this.data.toString();     } } | 
◆双链表的操作
| public class DbNodeTest {     public static void main(String[] args)     {        DbNode node1 = new DbNode("node1");        DbNode node2 = new DbNode("node2");        DbNode node3 = new DbNode("node3");        DbNode node4 = new DbNode("node4");                //add nodes generates a cycle double Linked List;        node1.next = node2;        node1.priv = node3;        node2.next = node3;        node2.priv = node1;        node3.next = node1;        node3.priv = node2;        System.out.println(node1.priv.priv.priv);        System.out.println("------------------");                //insert node4 between node1 and node2        node1.next = node4;        node4.priv = node1;        node4.next = node2;        node2.priv = node4;                System.out.println(node1.priv.priv.priv);        System.out.println("------------------");                //remove the node4        node1.next = node2;        node2.priv = node1;                System.out.println(node1.priv.priv.priv);        System.out.println("------------------");             } } | 
◆用LinkedList实现Stack
| public class MyStack {     private LinkedList list;          public MyStack()     {        list = new LinkedList();     }          public void push(Object obj)     {        if(null != obj)        {            list.addLast(obj);        }     }          public void pop()     {        list.removeLast();     }          public Object peek()     {         return list.getLast();     }          public boolean isEmpty()     {        return list.isEmpty();     }          public int size()     {        return list.size();     }          public String toString()     {        return this.list.toString();     } } | 
◆测试stack
| public class StackTest {     public static void main(String[] args)     {        MyStack stack = new MyStack();                stack.push("aaa");        stack.push("bbb");        stack.push("ccc");                System.out.println(stack.peek());        System.out.println(stack);                stack.pop();        System.out.println(stack);                System.out.println(stack.isEmpty());     } } | 
◆用LinkedList实现Queue
| public class MyQueue {     private LinkedList list;          public MyQueue()     {        list = new LinkedList();     }     public void inqueue(Object obj)     {        if(null != obj)        {            list.addLast(obj);        }     }          public Object dequeue()     {        return list.removeFirst();     }          public boolean isEmpty()     {        return list.isEmpty();     }          public int size()     {        return list.size();     }          public String toString()     {        return this.list.toString();     } } | 
◆测试Queue
| public class QueueTest {     public static void main(String[] args)     {        MyQueue queue = new MyQueue();                queue.inqueue("aaa");        queue.inqueue("bbb");        queue.inqueue("ccc");                System.out.println(queue);                queue.dequeue();                System.out.println(queue);                System.out.println(queue.isEmpty());     } } | 
HashSet
◆HashSet实现了Set接口,Set是一个不包含重复成员值的集合。只有要增加的成员在集合中满足为null时才会被增加成功(也就是说没有相同的值在集合中),所以通常要使自定义的类的对象添加时不重复的话,需要重写equals和hashCode方法。
◆Add
方法的判断条件为(e==null ? e2==null : e.equals(e2))
◆HashSet底层维护的是HashMap的KeySet集合,KeySet符合Set接口的特征。KeySet用一个Entry[]来实现,程序会根据key所给的hashCode值来计算它的位置,如果该位置无元素,则将它插入,有元素就再散列,直到找到没有元素的位置。HashSet会根据初始容量和负载因子来计算数组的容量,快满时会扩容。
| public class HashSetTest {     public static void main(String[] args)     {        //HashSet底层是维护一个HashMap对象,所有的操作都通过这个对象来完成。        //HashSet是一个添加不包含重复值的无序集合。        HashSet set = new HashSet();                set.add("a");        set.add("b");        set.add("c");        set.add("d");        set.add("e");        set.add("f");        set.add("g");        set.add("h");                //这行不会添加成功,因为String类重写了hashCode方法。        System.out.println(set.add("a"));                for(Iterator tr = set.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }             } } | 
◆     对于HashSet来说,如果添加的对象的hashCode相同,则不会被添加,否则调用equals方法判断增加的值是否在集合中已经存在,如果为true不添加,否则添加。
◆     当我们重写Object类的equals方法时,必须重写hashCode方法,反之亦然。
| public class HashSetTest2 {     public static void main(String[] args)     {        //HashSet是否会重复添加相同的元素的关键是,hashCode是否相同。        HashSet set = new HashSet();                Person person = new Person("aaa");                set.add(person);        set.add(new Person("bbb"));        set.add(new Person("ccc"));        set.add(new Person("ddd"));        set.add(person);//不会被添加 ,因为person是同一对象,hashCode相同。                set.add(new Person("aaa"));//这里被添加 了,因为这个对象的hashCode与前一个对象的hashCode不同。                //为了达到new Person("aaa")时,名称相同则不添加的目的,我们需要重写Object的equals和hashCode方法。        //重写后,则set.add(new Person("aaa"));就不会被执行了。                for (Iterator tr = set.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }                for (Iterator tr = set.iterator();
  tr.hasNext();)        {            System.out.println(tr.next().hashCode());        }     } } | 
| public class HashSetTest3 {     public static void main(String[] args)     {        HashSet set = new HashSet();                set.add(new Integer(4));        set.add(new Integer(2));        set.add(new Integer(3));        set.add(new Integer(1));                //这行不会添加成功,因为它本身重写了equals和hashCode方法。        //只有hashCode不同时才会被添加成功。        boolean flag = set.add(new Integer(4));                System.out.println(flag);                for(Iterator tr = set.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }     } } | 
TreeSet
◆TreeSet实现了SortedSet接口,这个接口提供了一个的有序的成员集合,它会按照自然升序排序或按照重写的comparator类的 compare方法进行排序。
TreeSet还实现了Set接口,所以也不能添加重复的成员,条件是hashCode不同时。
◆     所有插入到SortedSet集合中的成员,必须实现comparable接口或重写comparator类的 compare方法。
◆     TreeSet底层可以简单的看成是一个TreeMap的KeySet集合。
| public class TreeSetTest {     public static void main(String[] args)     {        //TreeSet是一个可以排序的集合,当要使用不同的排序规则时,可以自定义一个Comparator类,然后当参数传递。        //TreeSet不能包含重复的成员,条件是hashCode不同。        //TreeSet底层维护的其实是一个TreeMap对象。        TreeSet set = new TreeSet();                set.add("c");        set.add("a");        set.add("e");        set.add("d");        set.add("f");        set.add("a");                System.out.println(set);                for(Iterator iter = set.iterator();
  iter.hasNext();)        {            System.out.println(iter.next());        }     } } | 
◆对于自定义的类,是没有排序规则的,所以在使用TreeSet添加时,必须先定制好排序规则。否则会报ClassCastException
| public class TreeSetTest2 {     public static void main(String[] args)     {        TreeSet set = new TreeSet(new
  StudentScoreComparator());                Student s1 = new Student(10);        Student s2 = new Student(20);        Student s3 = new Student(30);        Student s4 = new Student(40);        Student s5 = new Student(50);                set.add(s1);        set.add(s2);        set.add(s3);        set.add(s4);        set.add(s5);                for(Iterator iter = set.iterator();
  iter.hasNext();)        {            System.out.println(iter.next());        }        } } //自定义排序的规则,让所有的学生按考试成绩进行排序 class StudentScoreComparator implements Comparator {     public int compare(Object arg0, Object arg1)     {        Student s1 = (Student)arg0;        Student s2 = (Student)arg1;                return s2.score-s1.score;     } } public class Student {     int score;          public Student(int score)     {        this.score = score;     }          public String toString()     {        return "Student [score=" + score + "]";     } } | 
◆对于系统提供的类型,一般已经指定好了排序规则,但是我们可以改变这个规则。
| public class TreeSetTest3 {     public static void main(String[] args)     {        TreeSet set = new TreeSet(new
  StringComparator());                set.add("c");        set.add("a");        set.add("e");        set.add("d");        set.add("f");        set.add("b");                System.out.println(set);             } } //自定义排序规则让字符串按降序排列 class StringComparator implements Comparator {     public int compare(Object arg0, Object arg1)     {        String str1 = (String)arg0;        String str2 = (String)arg1;        return str2.compareTo(str1);     } } | 
Collections类
常用方法
| public class CollectionTest {     public static void main(String[] args)     {        LinkedList list = new LinkedList();                list.add(new Integer(8));        list.add(new Integer(-20));        list.add(new Integer(20));        list.add(new Integer(-8));                //用Collections.reverseOrder()可以实现对原有集合的反序排序。        //Collections是一个用于操作集合的类,Collection是一个接口,两者不一样        Comparator r = Collections.reverseOrder();        Collections.sort(list,r);                for(Iterator iter = list.iterator();
  iter.hasNext();)        {            System.out.println(iter.next());        }                System.out.println("----------------");                //把原有集合的顺序打乱,每次运行都会产生不同的结果。        Collections.shuffle(list);                for(Iterator iter = list.iterator();
  iter.hasNext();)        {            System.out.println(iter.next());        }                System.out.println("----------------");                //取得集合中的最大值 和最小值         System.out.println(Collections.min(list));        System.out.println(Collections.max(list));     } } | 
HashMap
◆HashMap是一个基于Map接口实现的散列表,集合中包含的是一个个键值对的对象,不能包含重复的键,一个键至少要映射一个值,值是可以重复的。它相当于Dictionary类。
◆Map接口提供了三种集合的视图,分别是Keys,values和key-value
mappings
◆HashMap底层采有数组(Entry[])加单链表(Entry->Entry)的形式实现。
| static class Entry<K,V> implements Map.Entry<K,V>
  {         final K key;         V value;         Entry<K,V> next;         final int hash;         Entry(int h, K k, V v, Entry<K,V> n) {             value = v;             next = n;             key = k;             hash = h;        
  } } | 
基本操作:
| public class HashMapTest {     public static void main(String[] args)     {        //HashMap是一个键值 对映射的集合,底层维护的是一个Entry<k,v>对象。        //HashMap不包含重复的键,但是可以包含重复的值 ,一个键可以对应多个值 ,但是一个值 不能对应 多个健 。        //HashMap是一个无序的集合。        HashMap map = new HashMap();                map.put("1","aaa");        map.put("2","bbb");        map.put("3","ccc");        map.put("4","ddd");        map.put("5","aaa");                //因为keys是不能重复的,所以它的类型是set        Set keys = map.keySet();                for(Iterator tr = keys.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }        System.out.println("---------------");                //因为values是可以重复的,所以它的类型是Collection        Collection values = map.values();        for(Iterator tr = values.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }        System.out.println("---------------");                map.remove("5");        for(Iterator tr = keys.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }     } } | 
◆当使用自定义类时,如果不想在集合中添加重复的对象,可以重写equals和hashCode方法。当键相同时,后面的值会覆盖掉前面的值。
| public class HashMapTest2 {     public static void main(String[] args)     {        //当使用定义类时,如果不想出现重复的对象,要重写equals和hashCode方法。        //换句话说,就是HashMap健不重复的关键是hashCode是否相同,而不是对象是否相同。        HashMap map = new HashMap();                map.put(new Person("Bob"),"1");        map.put(new Person("John"),"2");        map.put(new Person("Mike"),"3");        map.put(new Person("Kate"),"4");                //这行在插入时,会将已存在键的值替换掉。而不是象set那样不让它插入。        map.put(new Person("John"),"5");                Set keys = map.keySet();                for(Iterator tr = keys.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }        System.out.println("---------------");                Collection values = map.values();        for(Iterator tr = values.iterator();
  tr.hasNext();)        {            System.out.println(tr.next());        }        System.out.println("---------------");     } } | 
◆在命令行中输入单词,统计每个单词出现的次数
| public class HashMapTest4 {     public static void main(String[] args)     {           HashMap map = new HashMap();                    for(int i = 0; i<args.length; i++)        {            if(map.containsKey(args[i]))            {               Integer value =
  (Integer)map.get(args[i]);               value = new
  Integer(value.intValue()+ 1);               map.put(args[i],value);            }            else            {               map.put(args[i],new Integer(1));            }        }                Set keys = map.keySet();                System.out.println(map);                for(Iterator iter = keys.iterator();
  iter.hasNext();)        {            String key = (String)iter.next();            int val = ((Integer)map.get(key)).intValue();            System.out.println(key + "=" + val);        }     } } | 
◆返回一个键值对视图
| public class HashMapTest5 {     public static void main(String[] args)     {        HashMap map = new HashMap();                map.put("a","aa");        map.put("d","dd");        map.put("c","cc");        map.put("b","bb");                //返回一个包含健值对的集合。类型是Map.Entry<k,v>.        Set set = map.entrySet();        for(Iterator iter = set.iterator();
  iter.hasNext();)        {            Map.Entry entry =
  (Map.Entry)iter.next();                        String key =
  (String)entry.getKey();            String val =
  (String)entry.getValue();                        System.out.println(key + ":" + val);        }     } } | 
TreeMap
◆TreeMap是一个基于NavigableMap接口实现的一个红黑树集合,可以按自然顺序或给定一个比较器进行排序。
◆一些基本的操作
| public class TreeMapTest {     public static void main(String[] args)     {        //TreeMap是一个有序的集合,不能包含重复的键,当插入相同键时,值会被替换,但是键只有一个。        //TreeMap底层维护的是一个Map.Entry<k,v>对象。        //当不想使用默认的排序方式时,可以使用Comparator创建自己的排序规则 。        TreeMap map = new TreeMap();                map.put("a","aa");        map.put("b","bb");        map.put("c","cc");        map.put("d","dd");        map.put("e","ee");        map.put("e","ff");                Set set = map.entrySet();        for(Iterator iter = set.iterator();
  iter.hasNext();)        {            Map.Entry entry =
  (Map.Entry)iter.next();                        String key =
  (String)entry.getKey();            String val =
  (String)entry.getValue();                        System.out.println(key + ":" + val);        }     } } | 
◆使用TreeMap的一个简单的例子
| /**  *  题目:随机生成50个数字(整数),每个数字的范围是[10,50],统计每个数字出     现的次数以及出现次数最多的数字与它的个数,最后将每个数字及其出现次数打印     出来,如果某个数字出现次数为0,则不要打印它。打印时按照数字的升序排列。  * @author Administrator  *  */ public class TreeMapTest3 {     public static void main(String[] args)     {        //存储数字及其出现的次数(key为数字,value为出现次数)。        TreeMap map = new TreeMap();                Random rand = new Random();        for(int i = 0; i<50; i++)        {            Integer key = new
  Integer(rand.nextInt(41)+ 10);            if(map.containsKey(key))            {               Integer val =
  (Integer)map.get(key);               val = new
  Integer(val.intValue()+ 1);               map.put(key,val);            }            else            {               map.put(key,new Integer(1));            }        }                Set set = map.entrySet();                Collection vals= map.values();        int max = ((Integer)Collections.max(vals)).intValue();                //存储出现次数最多的数字        List list = new ArrayList();                for(Iterator iter = set.iterator();
  iter.hasNext();)        {            Map.Entry entry =
  (Map.Entry)iter.next();                        Integer key =
  (Integer)entry.getKey();            Integer val =
  (Integer)entry.getValue();                        if(max == val.intValue())            {               list.add(key);            }                        System.out.println(key + ":" + val);        }                System.out.println("----------------");        System.out.println("出现次数最多的是" + max + "次");                for(Iterator iter = list.iterator();
  iter.hasNext();)        {            Integer val = (Integer)iter.next();            System.out.println(val);        }     } } | 
◆当要想在TreeMap中添加自定义的类的对象时,要实现一个比较器,告诉TreeMap按什么排序。
| public class TreeMapTest2 {     public static void main(String[] args)     {        TreeMap map = new TreeMap(new
  NameComparator());                map.put(new Person("Bob"),"1");        map.put(new Person("John"),"2");        map.put(new Person("Mike"),"3");        map.put(new Person("Kite"),"4");        map.put(new Person("Judy"),"5");        map.put(new Person("Judy"),"6");                Set set = map.entrySet();        for(Iterator iter = set.iterator();
  iter.hasNext();)        {            Map.Entry entry =
  (Map.Entry)iter.next();                        String key =
  ((Person)entry.getKey()).name;            String val =
  (String)entry.getValue();                        System.out.println(key + ":" + val);        }     } } //实现自己的比较器 class NameComparator implements Comparator {     public int compare(Object arg0, Object arg1)     {        Person p1 = (Person)arg0;        Person p2 = (Person)arg1;                return p2.name.compareTo(p1.name);     } } | 
以前版本遗留下来的一些集合类
Vector
◆Vector与ArrayList相似,但是Vector是同步的。Vector底层实现也与ArrayList近似,只不是扩容是为原来容量的2倍。使用上没有多大的区别,现在已很少使用。
| public class VectorTest {     public static void main(String[] args)     {        Vector vector = new Vector();                vector.add("aaa");        vector.add("bbb");        vector.add("ccc");        vector.add("ccc");                for(int i = 0; i<vector.size(); i++)        {            System.out.println(vector.get(i));        }     } } | 
Properties
◆Properties代表一个属性的持久化集合,它可以被保存到一个流中,也可以从一个流中加载。实现了Map<Object,Object>接口,继承自Hashtable<Object,Object>类。
◆可以调用load(Reader) / store(Writer, String)方法来将Properties对象存放到文件中。也可以调用 loadFromXML(InputStream) and storeToXML(OutputStream, String, String)来存取到一个xml文件中。
◆获取系统中的属性并打印出来
| public class PropertiesTest {     public static void main(String[] args)     {        Properties p = System.getProperties();                Set set = p.keySet();                for(Iterator iter = set.iterator();
  iter.hasNext();)        {            String key = (String)iter.next();            String val = p.getProperty(key);            System.out.println(key + " : " + val);        }     } } | 

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号