Java集合框架——Collection接口

一、Collection接口概述

在认识Collection接口的各个子接口之前,我们需要对它们之间的继承关系有个大概的了解。

Collection接口继承关系:

​​​根据图中继承关系,我们可以看出Collection接口包含两大分支,分别为:List接口和Set接口

  •  List接口 :有序队列,元素可重复
  •  Set接口 :无序队列,元素不能重复

二、List接口 

2.1 List接口扩展方法

方法 描述
public  E  get  (int   index ); 根据索引取得保存数据
public  E  set(int  index , E  element); 修改数据

注:List子接口与Collection接口相比最大的特点在于其有一个get()方法,可以根据索引取得内容。


由于List本身还是接口,要想取得接口的实例化对象,就必须有子类,在List接口下有三个常用子类:ArrayList、Vector、LinkedList。

2.2 ArrayList子类

ArrayList是一个针对于List接口的数组实现,它将元素存储在一个数组中,该数组是动态创建的。超过数组的容量时,则创建一个更大的数组并将当前数组中的所有元素复制到新数组中。

接下来,让我们来看看ArrayList子类的具体使用:

范例1:利用get方法取得数据

public class Test {
    public static void main(String[] args) {
        //此时集合里只保存String类型数据
        List <String> list=new ArrayList<>();
        list.add("hello");
        list.add("word");
        list.add("hello");//list允许元素重复
        System.out.println(list.size());
        System.out.println(list.contains("java"));
        System.out.println(list);
        //利用get方法结合索引取得数据
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }
}

上述代码中get()方法是List子接口提供的。如果现在操作的是Collection接口,那么此时想要取得数据,只能将集合变为对象数组进行操作。

范例2:Collection接口取得数据

public class Test {
    public static void main(String[] args) {
        //此时集合里只保存String类型数据
        List <String> list=new ArrayList<>();
        list.add("hello");
        list.add("word");
        //toArray()方法将集合变为对象数组返回
        Object[] result=list.toArray();
        System.out.println(Arrays.toString(result));//调用数组的toString()方法将对象转换为字符串类型输出
        }
    }

在实际开发中,集合中保存最多的数据类型,就是简单Java类

范例3:向集合保存简单Java类对象

class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.name=name;
        this.age=age;
        }
    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;
    }
    @Override
    public String toString(){
     return "person{"+"name:"+name+" "+"age:"+age+"}";
    }

    @Override
    public boolean equals(Object o){
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        //将Object类对象向下强制转换为Person类
        Person person = (Person) o;
        return Objects.equals(name, person.name) &&
                Objects.equals(age, person.age);
    }
}

public class Test {
    public static void main(String[] args) {
        List<Person> list=new ArrayList<>();
        list.add(new Person("rachel",18));
        list.add(new Person("monica",20));
        // 集合类中contains()、remove()方法需要equals()支持
        list.remove(new Person("monica",20));
        System.out.println(list.contains(new Person("rose",12)));
        for (Person p: list) {
            System.out.println(p) ;
        }
    }
}

注:集合操作简单java类时,对于remove()、contains()方法需要equals()方法支持。

2.3 LinkedList子类

LinkedList是实现list接口的一个双向链表,除了实现List接口的方法外,该类还提供了从线性表两端提取、插入、删除元素的方法。

方法 描述
public void  addFirst (E  e) 从该线性表的头部添加一个元素
public void  addLast (E  e) 从该线性表的尾部添加一个元素
public  E  getFirst ( ) 返回该线性表的第一个元素
public  E  getLast ( ) 返回该线性表的最后一个元素
public  E  removeFirst ( ) 返回并删除该线性表的第一个元素
public  E  removeLast ( ) 返回并删除该线性表的最后一个元素

总结:ArrayList和LinkedList的区别

2.4 Vector子类

Java集合框架是在JDK1.2中引入的,在JDK1.2之前的版本也支持一些数据结构,其中就有Vector类,为了适应Java集合框架,这些类进行了重新设计,但是为了保证兼容性,保留了它们的所有方法。

在JDK1.2中,Vector类除了包含用于访问和修饰向量的同步方法外,它与ArrayList的操作是相同的。

2.5 ArrayList与Vector区别

1. 历史时间:ArrayList是从JDK1.2提供的,而Vector是从JDK1.0就提供了。
2. 处理形式:ArrayList是异步处理,性能更高;Vector是同步处理,性能较低。
3. 数据安全:ArrayList是非线程安全;Vector是性能安全。
4. 输出形式:ArrayList支持Iterator、ListIterator、foreach;Vector支持Iterator、ListIterator、foreach、Enumeration。 

三、Set接口

 Set接口是Collection的子接口,它并没有引入新的方法和常量,只是规定它的实例不能包含相同的元素,也就是说,在一个规则集中,一定不存在元素e1、e2使得e1.equals(e2)的返回值是true.

Set接口有两个常用的子类:HashSet(无序存储)、TreeSet(有序存储)

3.1 树形集TreeSet

SortedSet是Set的一个子接口,它保证规则集中的元素是有序的,TreeSet是实现SortedSet接口的一个具体类,只有当对象之间可以相互比较时,才可以将它们添加到树形集TreeSet中,有两种方法可以实现对象的比较(正对对象数组进行的排序处理):

(1)使用Comparable接口,由于添加到规则集内的对象是Comparable的实例,所以它们可以使用CompareTo方法来进行比较,并且所有属性必须全部进行比较操作。

(2)如果该类不支持Comparable接口,或者在实现Comparable接口的类中不想使用CompareTo方法进行比较,可以给规则集的元素指定一个比较器

范例:使用TreeSet排列

class Person implements Comparable<Person> {
    private String name ;
    private Integer age ;
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age ) {
            return 1 ;
        }else if (this.age < o.age ){
            return -1 ;
        }else {
            return this.name.compareTo(o.name) ;
        }
    }
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args) {
        Set<Person> set = new TreeSet<>() ;
        set.add(new Person("张三",20)) ;
                // 重复元素
        set.add(new Person("张三",20)) ;
        set.add(new Person("李四",20)) ;
        set.add(new Person("王五",19)) ;
        System.out.println(set) ;
    }
}

3.2散列集HashSet

 HashSet类是一个实现Set接口的具体类,它可以用来存储互不相同的任何元素,考虑效率的因素,添加到HashSet之中的对象必须实现hashCode()方法,适当地散列分布散列码。

在使用TreeSet子类进行数据保存的时候,重复元素的判断依靠的ComParable接口完成的。但是这并不是全部Set
接口判断重复元素的方式,因为如果使用的是HashSet子类,由于其跟Comparable没有任何关系,所以它判断重
复元素的方式依靠的是Object类中的两个方法:

  1. hash码: public native int hashCode();
  2. 对象比较:public boolean equals(Object obj);

在Java中进行对象比较的操作有两步:第一步要通过一个对象的唯一编码找到一个对象的信息,当编码匹配之后再
调用equals()方法进行内容的比较。

范例:覆写hashCode()与equals()方法消除重复

class Person implements Comparable<Person> {
    private String name ;
    private Integer age ;
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) &&
                Objects.equals(age, person.age);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age ) {
            return 1 ;
        }else if (this.age < o.age ){
            return -1 ;
        }else {
            return this.name.compareTo(o.name) ;
        }
    }
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args) {
        Set<Person> set = new HashSet<>() ;
        set.add(new Person("张三",20)) ;
// 重复元素
        set.add(new Person("张三",20)) ;
        set.add(new Person("李四",20)) ;
        set.add(new Person("王五",19)) ;
        System.out.println(set) ;
    }
}
发布了50 篇原创文章 · 获赞 39 · 访问量 8288

猜你喜欢

转载自blog.csdn.net/Racheil/article/details/89421675