Java集合简述(一)

来源:互联网 发布:巨人的陨落 知乎 编辑:程序博客网 时间:2024/04/25 14:55


Java集合简述(一)

   集合(Collection接口):用以存储对象;长度可变;课存放多种类型

                                       集合存放的是对象地址(引用)

                                       常见子接口:List   Set

   下面先讲以一些Collection接口中定义的关于集合共有的方法:            

     1,添加
    add(Object obj); 向集合添加对象
    addAll(collection);向集合添加一组对象

    2,删除
    remove(Object obj);  删除指定对象
    removeAll(collection c);  删除c中存在的对象
    clear();  清空集合

   3,判断。
    contains(Object obj);  判断集合中是否存在指定对象
    isEmpty();  判断是否为空

   4,获取
    iterator();  返回集合上的迭代器(Iterator)

          Iterator提供的方法有:

                     hasNext():判断下面是否还有元素,如果有返回true,否则返回false             

              next():获取迭代器中的下一个元素

              remove():删除当前元素(集合中的元素同时被删除)


    size();  获取集合内对象个数

  5,获取交集。
    retainAll(collection c); 只保留与c集合中相同的对象

  6,集合变数组。
    toArray();

1.集合的子接口 List

   List中的元素有序,可以重复,以索引访问元素。下面介绍一下List特有的方法:

   增:

       add(int index,E e):指定位置添加元素

       addAll(int index,Collection c):指定位置添加一组元素

   删:  

        remove(int index):删除指定索引处的元素

   改:

        set(int index,E e):修改指定位置的元素

    查: 

        get(int index):通过索引获取元素

        indexOf(Object o):获取对象第一次出现位置的索引

        lastindexOf(Object o):获取对象最后一次出现位置的索引

        subList(int first , int end):获取集合中索引从first到end的元素

                                                (不包含索引为end的元素)

        listIterator():获取ListIterator迭代对象

                  List集合特有的迭代器。ListIterator是Iterator的子接口。

 

       注意:在迭代时,不可以通过集合对象的方法操作集合中的元素。

                  因为会发生ConcurrentModificationException异常。

 

                 所以,在迭代器时,只能用迭代器的方法操作元素,

                可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,

                 如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。

 

                 该接口只能通过List集合的listIterator方法获取。

                 ListIterator的方法:(ListIterator的所有方法均在当前访问的位置操作)

                                  add(E e):添加元素

                                  set(E e):修改元素

                                  hasPrevious():判断前面有没有元素,用于逆向遍历

                                  previous():返回前一个元素

       注意:在List中的contains(Objectobj):判断集合中是否存在指定对象

                  和remove()函数,底层都是调用equals()函数

  1.1 实现List接口的具体类:ArryList

       ArryList底层使用数组数据结构。特点:查询速度很快;但是增删稍慢。线程不同步。

        ArryList没有特殊的函数用法,下面用一个例子来具体看一下ArryList的用法:

class  ArryListDemo
{
    public static void main(String[] args)
    {
        ArrayList al = new ArrayList();

        //添加元素。
        al.add("java01");          //add(Object obj);
        al.add("java02");
        al.add("java03");
        al.add("java04");

        for(Iterator it = al.iterator(); it.hasNext() ; )     //获取迭代器,用于取出集合中的元素。
        {
             System.out.println(it.next());
        }

        //打印原集合。
        System.out.println("原集合:"+al);

        //删除元素。
        al.remove("java02");

        //判断元素。
         System.out.println("java03是否存在:"+al.contains("java03"));
         System.out.println("集合是否为空?"+al.isEmpty());


        //获取个数。集合长度。
         System.out.println("size:"+al.size());

        //打印改变后的集合。
         System.out.println(al);

         al.clear();//清空集合。
}

1.2 实现List接口的具体类:LinkedList

     LinkedList底层使用链表数据结构。特点:增删速度很快;查询稍慢。线程不同步

    LinkedList有自己的一些特殊函数,介绍如下:

                       addFirst():在开头位置添加元素

                       addLast():在末尾添加元素


                       removeFirst():删除并返回一个元素    (列表为空时抛出异常)

                       removeLast():删除并返回最后一个元素

                        

                       getFirst():获取第一个元素

                       getLast():获取最后一个元素

 

                       在JDK1.6出现了上述方法的替代方法,如下:

                      offerFirst();    添加元素

                      offerLast(); 

 

                     pollFirst();

                     pollLast();

                     获取元素,但是元素被删除。如果集合中没有元素,会返回null。


                      peekFirst();

                      peekLast();

                      获取元素,但不删除元素。如果集合中没有元素,会返回null。

2.集合的子接口Set

   元素无序,不可以重复,无索引。具有的方法和Collection一样。下面主要介绍它的两个子类:

2.1 实现Set接口的具体类 HashSet

     HashSet底层数据结构为哈希表

     因为Set集合中的元素不允许重复,所以在存储的时候,HashSet必须要保证元素的唯一性。

     HashSet通过元素的两个方法,hashCode()和equals()来保证元素的唯一性。

     用HashSet存储自定义对象时,一般会在自定义的对象类里重写hashCode()和equals()函数。

    hashCode()返回对象的哈希值,也就是地址值,存储时首先调用hashCode()函数

    如果元素的HashCode值相同,才会判断equals()是否为true。

     如果元素的hashCode值不同,不会调用equals()。

     注意对于判断元素是否存在,以及删除等操作,依赖的方法都是元素的hashCode和equals方法。

    下面通过例子再来看一下:定义一个描述人的类,通过hashSet集合存储姓名和年龄相同为同一个人,重复元素。

class HashSetTest
{
    public static void main(String[] args)
    {
        HashSet hs = new HashSet();

        hs.add(new Person("a1",11));
        hs.add(new Person("a2",12));
        hs.add(new Person("a3",13));
        hs.add(new Person("a2",12));
        hs.add(new Person("a4",14));

       System.out.println("a1:"+hs.contains(new Person("a2",12)));  //判断hs中是否存在new Person("a2",12)
            
        hs.remove(new Person("a4",13));   //删除new Person("a4",13)
        

        Iterator it = hs.iterator();      //获取迭代对象

        while(it.hasNext())
        {
            Person p = (Person)it.next();
           System.out.println(p.getName()+"::"+p.getAge());
        }
    }
}
class Person
{
    private String name;
    private int age;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    
    public int hashCode()
    {
        return name.hashCode()+age*37;     //重写hashCode函数,尽量使不同的对象返回不同的哈希值
    }

    public boolean equals(Object obj)        //重写equals函数,根据需求重写判定条件
    {

        if(!(obj instanceof Person))
            return false;

        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
}        
               

 

2.2 实现Set接口的具体类 TreeSet

        TreeSet底层数据结构为二叉树

      可以自动对Set集合中的元素进行排序

      存储自定义对象时必须实现Compareable接口,

      覆写int compareTo(Object o)方法,指定比较方式 使对象具有比较性。

      返回1:this > o                                                                                          

      返回0:this = o                       保证元素唯一性的依据:compareTo方法return 0

      返回-1:this < o     

      TreeSet通过compareTo函数的返回值来对集合中的元素进行排序。                                                                              

      当compareTo()方法返回0时,系统默认两个对象为同一对象,所以当对象有多个属性时,必须比较多次

      即排序时,当主要条件相同时,一定判断一下次要条件。如下所示:

class TreeSetDemo
{
    public static void main(String[] args)
    {
        TreeSet ts = new TreeSet();

        ts.add(new Student("lisi02",22));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi09",19));
        ts.add(new Student("lisi08",19));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi01",40));

        Iterator it = ts.iterator();
        while(it.hasNext())
        {
            Student stu = (Student)it.next();
            System.out.println(stu.getName()+"..."+stu.getAge());
        }
    }
}
class Student implements Comparable      //该接口强制让学生具备比较性。
{
    private String name;
    private int age;

    Student(String name,int age)
    {
        this.name = name;
        this.age = age;
    }

    public int compareTo(Object obj)                        //根据需求,重写compareTo方法,告诉TreeSet排序依据
    {
        if(!(obj instanceof Student))
            throw new RuntimeException("不是学生对象");
        Student s = (Student)obj;

        if(this.age>s.age)              //首先按年龄排序
            return 1;
        if(this.age==s.age)
        {
            return this.name.compareTo(s.name);            //当年龄相同是再按姓名比较
        }
        return -1;
    }
    public String getName()
    {
        return name;

    }
    public int getAge()
    {
        return age;
    }
}

TreeSet还有第二种排序方式。

当元素自身不具备比较性时,或者具备的比较性不是所需要的。

这时就需要让集合自身具备比较性。

在集合初始化时,就有了比较方式:创建TreeSet对象时,传入一个比较器:

比较器:定义一个类,实现Comparator接口,覆盖compare方法。

class 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;
    }
}
class TreeSetDemo2
{
    public static void main(String[] args)
    {
        TreeSet ts = new TreeSet();

        ts.add(new Student("lisi02",22));
        ts.add(new Student("lisi02",21));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi09",19));
        ts.add(new Student("lisi06",18));
        ts.add(new Student("lisi06",18));
        ts.add(new Student("lisi007",20));

        Iterator it = ts.iterator();
        while(it.hasNext())
        {
            Student stu = (Student)it.next();
            System.out.println(stu.getName()+"..."+stu.getAge());
        }
    }
}

class MyCompare implements Comparator          //自定义的比较器
{
    public int compare(Object o1,Object o2)
    {
        Student s1 = (Student)o1;
        Student s2 = (Student)o2;

        int num = s1.getName().compareTo(s2.getName());          //按姓名排序
        if(num==0)
        {
            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));   //当姓名相同是按年龄排序
        }
        return num;
    }
}

当两种排序都存在时,以比较器为主。而且在写程序的时候多使用比较器方式。

原创粉丝点击