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类中的两个方法:
- hash码: public native int hashCode();
- 对象比较: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) ;
}
}
上一篇: Java多线程—— 线程的3种创建方式
下一篇: JAVA集合框架之Collection