一 我所知道的集合 
  我知道的第一个集合: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 */
/**//* Class StudyComparable */
 package conllection;
package conllection;

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


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


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


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



 /**//* Class Person */
/**//* Class Person */

 package conllection;
package conllection;


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


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

 @Override
    @Override

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

 @Override
    @Override

 public String toString()
    public String toString()  {
{
 return name + "/" + age;
        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;
package conllection;

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


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


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


 class NameComparator implements Comparator<Person>
    class NameComparator implements Comparator<Person>  {
{

 @Override
        @Override

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

 }
    }


 class AgeComparator implements Comparator<Person>
    class AgeComparator implements Comparator<Person>  {
{

 @Override
        @Override

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

 }
    }


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

 NameComparator nc = new NameComparator();
        NameComparator nc = new NameComparator();
 Collections.sort(psn, nc);
        Collections.sort(psn, nc);
 System.out.println("onName:" + psn);
        System.out.println("onName:" + psn);
 AgeComparator ac = new AgeComparator();
        AgeComparator ac = new AgeComparator();
 Collections.sort(psn, ac);
        Collections.sort(psn, ac);
 System.out.println("onAge:" + psn);
        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 阅读(1231) 
评论(3)  编辑  收藏  所属分类: 
学习心得