黑马程序员技术交流社区

标题: List与Set集合的小结 [打印本页]

作者: 谭立文    时间: 2012-10-8 11:34
标题: List与Set集合的小结
List和Set都是Collection的子接口
Collection
|-----List                      (有序,可重复)
|         |-----Vector            特点:线程安全
|        |-----ArrayList         特点:不具线程安全,底层用数组来实现的,有序,适合存放查询,修改比较频繁的操作。
|        |-----LinkedList        特点:不具线程安全,底层用链表来实现,有序,适合对元素的增删操作。
|
|-----Set                       (不可重复)
|        |-----HashSet     此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
        |-----LinkedHashSet  具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现.
        |-----TreeSet




总结之List集合:
        由于Vector是线程安全的,同步的,在一般情况下,为了考虑到程序运行的效率问题,很多时候我们都选择使用ArrayList,Vector渐渐的也被ArrayList所取代。
        关于继承了AbstractList类,特有迭代器ListIteraotr的一点小细节:
package com.wenfengkeji.collection;
import java.util.ArrayList;
import java.util.ListIterator;
public class ArrayListDemo {
        public static void main(String[] args) {
                ArrayList<Person> al = new ArrayList<Person>();
                al.add(new Person("a", 18));
                al.add(new Person("b", 16));
                al.add(new Person("c", 20));
                al.add(new Person("d", 21));
                ListIterator<Person> lt = al.listIterator();
                while(lt.hasNext())
                {
                        Person p = lt.next();
                        if(p.getName().equals("a"))
                        {
                                                     //al.add(new Person("ok", 21)); //出错
                                System.out.println(al.size());
                                lt.remove();    //若remove在add之后抛IllegalStateException
                                lt.add(new Person("ok", 21));
  /*
   * lt.remove();
   * 从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
   * 对于每个 next 或 previous 调用,只能执行一次此调用。只有在最后一次调用 next
   * 或 previous 之后,尚未调用 ListIterator.add 时才可以执行该调用。
   */
                                System.out.println(al.size());
                        }
                }
                System.out.println(al);
        }
}
---------------------------------------------------------------------------------------------------------

总结之HashSet、LinkedHashSet集合:
         HashSet集合的主要特点是:不保证顺序(若用LinkedHashSet可以做到按添加时的顺序),因为底层是用Map来实现,唯一性:1.hashCode、equals
元素被添加到 HashSet集合的过程:
    首先被添加对象调用该对象的hashCode方法获得hashCode,根据该hashCode寻找HashSet集合所在的内存单元,若两个不同的对象具有相同的hashCode则会调用
equals方法进一步进行比较,具体的比较方式可以自己去实现,默认的比较的是两个对象的引用,若引用相同则不会被添加到集合中,一般我们会自己重写hashCode方法和equlas方法来避免重复添加的问题,因为hashCode的默认计算方式是根据对象的内存地址信息来计算出的,是一个native方法。
    若没有hash冲突则该对象就直接被添加到集合当中了,不会再调用equlas。
    值得注意的是若某个类依据其某个或某些Filed重写了hashCode方法,在该对象被添加到集合中之后,若修改了该对象参与计算hashCode值得字段,则该对象将不能够再通过
集合的public boolean remove(Object o)方法从集合当中移除了,因为HashSet集合(这种数据结构)就是依靠计算元素的hashCode值来在集合所开辟的那段内存单元中查找、定位到存放元素的位置的,若出现这种情况就发生内存泄露,应该特别注意。
----------------------------------------------------------------------------------------------------------
总结之TreeSet集合:
        TreeSet集合也是属于Set集合体系的成员之一,该集合的主要功能是可以按一定规则对元素(对象)在添加到集合的过程中就对其进行排序。
其底层是用二叉树这种数据结构来实现的。
        想要添加到集合中的元素排序,有两种实现方式
        第一种是让元素具有可比较性,即实现java.lang.Comparable接口
实现int compareTo(T o)方法,若返回值为0 表示当前正在考虑被添加的元素与被比较的元素具有相同的意义,将不会被添加到集合当中,若  < 0 表示当前正在考虑被添加的元素在逻辑上应该排在被比较元素之后,若 > 0,则正在考虑被添加的元在当前被比较元素之前。   
        第二种是让集合自身具有某种可比较性规则,即将某个实现了比较器Compartor的类传递给集合,让集合具有这种比较规则。
实现public int compare(Object o1, Object o2);这个与compareTo(Object obj)类似。

关于第二种方式的需求分析:因为有时时候被人给你了一个类像java.lang.String 已经将该方法实现了,我在添加String元素到集合当中时我不想用String默认的比较方式,这个时候
就只能使用第二种了。

package com.wenfengkeji.collection;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
/*
* TreeSet 能够保证数据的唯一性,并能够对元素进行排序
* 保证唯一性的标准:既不是依靠hashcode也不依靠equlas方法
* 而是根据compareTo方法的返回值
* 若为0表示有重复的不添加
* 若为-1排在当前this所对应的元素之后
* 若为1排在当前this所对应的元素之前
*
* 需求:按照年龄的从小到大顺序进行排序
* 若年龄相同按照姓名
*/
        public static void main(String[] args) {
                comparator();
        }
/*
* 让集合自身具有比较性
*/
public static void comparator() {
        TreeSet<Person> ts = new TreeSet<Person>(new Comparator(){
                @Override
                public int compare(Object o1, Object o2) {
                        Person p1 = (Person)o1;
                        Person p2 = (Person)o2;
                        int temp = p1.getAge() - p2.getAge();
                        return temp == 0 ? p1.getName().compareTo(p2.getName()):temp;
                }
               
        });
        ts.add(new Person("aa",21));
        ts.add(new Person("ca",19));
        ts.add(new Person("aa",22));
        ts.add(new Person("za",19));
        for(Person p : ts)
        {
                System.out.println(p);
        }
}

        public static void comparable() {
                TreeSet<Person> ts = new TreeSet<Person>();
                ts.add(new Person("aa",21));
                ts.add(new Person("ca",19));
                ts.add(new Person("aa",22));
                ts.add(new Person("za",19));
                for(Person p : ts)
                {
                        System.out.println(p);
                }
        }
}
class Person implements Comparable
{
        private String name;
        private int age;
        public Person(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public String toString()
        {
                return this.name + ":" + this.age;
        }
        @Override
        public int compareTo(Object o) {
                if(o == null)
                        return 0;
                if(!(o instanceof Person))
                        throw new ClassCastException();
                Person p = (Person)o;
                int temp = this.age - p.age;
                return temp == 0 ? this.name.compareTo(p.name):temp;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
       
}




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2