随笔-42  评论-42  文章-0  trackbacks-0
一 我所知道的集合 

  我知道的第一个集合:ArrayList,加入元素非常方便,add(Object elem)。其它的, TreeSet(有序并防止重复), HashMap(名值对), LinkedList(为经常插入或删除中间元素所设计的高效集合), HashSet(防止重复,可快速找寻符合的元素), LinkedHashMap(类型于HashMap, 但可以记住元素插入的顺序,也可以设定成依照元素上次存取的先后来排序)。总的来说,这些集合可以用“顺序”和“重复”来区分。

  下面两图用来说明3个主要的接口:List, Set 和 Map.(部分)



二 顺序

  顺序问题,可以用TreeSet或Collections.sort()来实现。当插入新元素时,TreeSet会花时间找到适当的位置,所以相对要慢了。而ArrayList只要把新加的元素放到最后就好。(当然,ArrayList也有重载的add(index, element )可以插到指定位置,也慢,通常不这样做。)
  sort(List<T> list) 方法 /* public static <T extends Comparable<? super T>> void sort(List<T> list) */ :只传入Comparable 接口的 list 作为参数。Comparable有一个方法要实现:compareTo(T o)方法。
  或者用重载的sort()方法:sort(List<T> list, Comparator< ? super T> c)方法 。这样,就用不着compareTo()方法了。而是要实现Comparator接口,实现compare()方法。
 
实例1-关于 sort(List<T> list)

/* Class StudyComparable */
package conllection;

import java.util.Collections;
import java.util.LinkedList;

public class StudyComparable {
    LinkedList
<Person> psn = new LinkedList<Person>();

    
public static void main(String[] args) {
        StudyComparable sc 
= new StudyComparable();
        sc.go();
    }


    
private void go() {
        psn.add(
new Person("one"3));
        psn.add(
new Person("two"2));
        psn.add(
new Person("three"5));
        psn.add(
new Person("five"6));
        psn.add(
new Person("eight"8));
        System.out.println(psn);
        Collections.sort(psn);
        System.out.println(psn);
    }

}



/* Class Person */

package conllection;

public class Person implements Comparable<Person> {
    String name;
    
int age;

    
public Person(String n, int a) {
        name 
= n;
        age 
= a;
    }


    @Override
    
public int compareTo(Person o) {
        
return name.compareTo(o.name);
    }


    @Override
    
public String toString() {
        
return name + "/" + age;
    }

}


运行结果:
  [one/3, two/2, three/5, five/6, eight/8]
        [eight/8, five/6, one/3, three/5, two/2]

  现在,可以按照name来排序了,不过我想用age 来排序,就要改代码,用Person类中的compareTo()方法进入age的比较。这样做很不好,所以可以用重载的sort(List<T> list, Comparator<? super T> c)方法。

实例2-关于 sort(List <T> list, Comparator <? super T> c)

Class StudyComparator
package conllection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class StudyComparator {
    ArrayList
<Person> psn = new ArrayList<Person>();

    
public static void main(String[] args) {
        StudyComparator sc 
= new StudyComparator();
        sc.go();
    }


    
class NameComparator implements Comparator<Person> {

        @Override
        
public int compare(Person o1, Person o2) {
            
return o1.name.compareTo(o2.name);
        }


    }


    
class AgeComparator implements Comparator<Person> {

        @Override
        
public int compare(Person o1, Person o2) {
            
return o1.age - o2.age;
        }


    }


    
private void go() {
        psn.add(
new Person("one"3));
        psn.add(
new Person("two"2));
        psn.add(
new Person("three"5));
        psn.add(
new Person("five"6));
        psn.add(
new Person("eight"8));
        System.out.println(psn);

        NameComparator nc 
= new NameComparator();
        Collections.sort(psn, nc);
        System.out.println(
"onName:" + psn);
        AgeComparator ac 
= new AgeComparator();
        Collections.sort(psn, ac);
        System.out.println(
"onAge:" + psn);
    }

}


  Class Person:同例1中的Person.Class 。因为在StudyComparator里面定义了Comparator的实现类,所以Person类不用动,也就是说,在没有原代码的情况下也实现了sort,而且可按不同的属性来进行排序,我更喜欢这个重载的sort()方法。

运行结果:

[one/3, two/2, three/5, five/6, eight/8]
onName:[eight/8, five/6, one/3, three/5, two/2]
onAge:[two/2, one/3, three/5, five/6, eight/8]


三 重复

  1 相等 ==

  防止重复,用Set。要解决的第一个问题:两个对象的引用怎样才算是重复?答案就是它们是相等的。那么怎样算‘相等’?显然不是单纯的值相等。‘相等’包括引用相等和对象相等。
  引用相等:引用堆上的同一对象的两个引用是相等的。如果对两个引用调用hashCode() ,会得到相同的结果。hashCode()(默认的行为)会返回对象在堆上的特有的唯一序号。显然,不同对象的引用的hashCode()的值是不同的。
  对象相等:堆上的两个不同对象,在意义上相同。
  因此,想要两个不同的对象‘相等’,就必须要override hashCode()和equals()方法

  
a.equals(b) 的默认行为是执行‘==’,包括了hashCode()的对比。如果equals()方法不被override, 那么两个对象永远都不会视为相同。

  2 HashSet 检查重复:hashCode() 与 equals()

  当把对象放入HashSet时,它会先用对象的hashCode()与已有元素的hashCode()来比较,(如果没有override过hashCode()方法,那么HashSet 会认为对象间不重复,我们当然要override来确保对象有相同的值)。如果hashCode()相同,再调用其中一个的equals()来检查对象是否真的相同。如果又相同了,那么加入的操作就不会发生。

  说明:有相同hashCode()的对象也不一定是相等的,感觉有点怪,但的确如此。因为hashCode()用的是杂凑算法,也许刚好使多个对象有了相同的杂凑值。越烂的杂凑算法越容易碰撞。这个属于数据结构方面的问题了。具体的要问专家了。
posted on 2008-07-09 02:47 BlueSunshine 阅读(1162) 评论(3)  编辑  收藏 所属分类: 学习心得

评论:
# re: 学习集合与泛型 2008-07-10 12:07 | BlueSunshine
四 使用TreeSet

  防止重复又保持有序,可以用TreeSet。

例3-关于TreeSet 的例子,通过实现Comparator来达到排序。

package collection;
 
2 
 
3 import java.util.Comparator;
 
4 import java.util.TreeSet;
 
5 
 
6 public class TestTree {
 
7     public static void main(String[] args) {
 
8         new TestTree().go();
 
9     }
10 
11     private void go() {
12         Book b1 = new Book("How Cats Work");
13         Book b2 = new Book("Remix you body");
14         Book b3 = new Book("Finding Emo");
15 
16         SetComparator sc = new SetComparator();
17         TreeSet<Book> tree = new TreeSet<Book>(sc);
18 
19         tree.add(b1);
20         tree.add(b2);
21         tree.add(b3);
22         tree.add(b3);
23         System.out.println(tree);
24     }
25 
26     class SetComparator implements Comparator<Book> {
27
 
28
         @Override
29         public int
 compare(Book o1, Book o2) {
30             return
 o1.title.compareTo(o2.title);
31
         }
32
 
33     }
34 }
35 
36 
37 package collection;
38 
39 public class Book {
40     String title;
41 
42     public Book(String t) {
43         title = t;
44     }
45 
46 
47     @Override
48     public String toString() {
49         return title;
50     }
51     
52 }
53 

  
例4-关于TreeSet的第2个例子,通过实现Comparable来达到排序

 1 package collection;
 2 
 3 import java.util.TreeSet;
 4 
 5 public class TestTree {
 6     public static void main(String[] args) {
 7         new TestTree().go();
 8     }
 9 
10     private void go() {
11         Book b1 = new Book("How Cats Work");
12         Book b2 = new Book("Remix you body");
13         Book b3 = new Book("Finding Emo");
14 
15         TreeSet<Book> tree = new TreeSet<Book>();
16 
17         tree.add(b1);
18         tree.add(b2);
19         tree.add(b3);
20         tree.add(b3);
21         System.out.println(tree);
22     }
23 
24 }
25 
26 package collection;
27 
28 
29 public class Book implements Comparable<Book> {
30     String title;
31 
32     public Book(String t) {
33         title = t;
34     }
35 
36     @Override
37     public int compareTo(Book o) {
38         return title.compareTo(o.title);
39     }
40 
41     @Override
42     public String toString() {
43         return title;
44     }
45 
46 }



  TreeSet的排序功能也是通过实现Comparator或Comparable来完成的。要么是TreeSet集合中的元素实现了Comparable,要么是用重载的Comparator作为参数来创建TreeSet。


  回复  更多评论
  
# re: 学习集合与泛型 2008-07-10 21:50 | BlueSunshine
五 泛型

1,泛型中的‘万用字符’:

<T extends  Comparable> :表示T是实现了Comparable的类型(在‘泛型’中extends表示extends或者implement)

<? extends T> :表示必须是T或者T的父型

ArrayList<? extends Animal> :以实现或继承Animal的类型为元素类型的ArrayList

2,相同功能的另一种语法:

public <T extends Animal> void takeThing(ArrayList<T> list);

等同于:public void takeThing(ArrayList<? extends Animal> list);   回复  更多评论
  
# re: 学习集合与泛型 2009-10-16 22:47 | 初学生
@BlueSunshine
前辈
<? extends T> :表示必须是T或者T的父型
怎么不是子型
  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: