欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java集合框架——Collection接口

程序员文章站 2024-02-06 23:46:58
...

一、Collection接口概述

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

Collection接口继承关系:

Java集合框架——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) ;
    }
}