Java---类集(ArrayList、Vector、LinkedList、HashSet、TreeSet)

一:什么是类集
从JDK1.2开始 ,Java提供了动态对象数组,解决了数组长度固定的问题。类集实际上属于动态对象数组。
在Java的类集里面(java.util包)提供了两个最为核心的接口:Collection、Map接口。
Collection是针对单个对象处理;
Map是针对键值对对象处理(key value)。

二:Collection接口

public interface Collection<E> extends Iterable<E>

Collection接口中常用方法如下:

boolean remove(Object o);
boolean add(E e);
void clear();
//取得集合的迭代器(遍历集合的工具)
Iterator<E> iterator();

Collection接口有两个使用频率很高的子接口List(允许重复元素),Set(不允许重复元素)。

三:List接口(90%,允许元素重复)

public interface List<E> extends Collection<E>

在List接口中,有2个独有的方法,根据索引来操作:

  • 根据指定索引修改相应元素
public E set(int index, E element);
  • 根据索引取得数据
public E get(int index);

实现List接口有3个常用子类:ArrayList、Vector、LinkedList。一般来说优先考虑ArrayList子类。

ArrayList类

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList中方法练习:

package CODE.类集;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Collection1 {
    public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        list.add("hello");
        list.add("pick");
        list.add("health");
        //可以添加重复数据
        list.add("pick");
        System.out.println(list.contains("pick")); //true
        list.remove("pick");
        list.set(0,"hai");
        for(int i=0;i<list.size();i++)
        {
            System.out.println(list.get(i));  //hai health pick
        }
    }
}

集合与简单Java类:

package CODE.类集;

import java.util.ArrayList;
import java.util.List;

//集合与简单Java类
class Student
{
    private int sno; //序号
    private String name; //姓名

    public Student(int sno, String name) {
        this.sno = sno;
        this.name = name;
    }
    //覆写equals方法
    public boolean equals(Object obj)
    {
        if(obj==null)
            return false;
        if(this==obj)
        {
            return true;
        }
        if(!(obj instanceof Student))
            return false;
        Student st=(Student)obj; //向下转型
        return sno==st.sno && name.equals(st.name);
    }

    @Override
    public String toString() {
        return "学号:"+sno+" 姓名:"+name;
    }
}
public class ListArray1 {
    public static void main(String[] args) {
        List<Student> list=new ArrayList<>();//ArrayList是list子类
        list.add(new Student(1,"a"));
        list.add(new Student(2,"b"));
        list.add(new Student(3,"c"));
        list.add(new Student(2,"b"));
        // 集合类中contains()、remove()方法需要equals()支持 ,所以需要覆写equals()方法
        System.out.println(list.contains(new Student(2,"b"))); //true
        list.remove(new Student(2,"b"));
        for(int i=0;i<list.size();i++)
        {
            System.out.println(list.get(i)); //学号:1 姓名:a    学号:3 姓名:c  学号:2 姓名:b
        }

    }
}

接口中要保存自定义的类对象,自定义类必须覆写equals();
类集contains()、remove()等方法需要调用equals()来判断元素是否相等。(equals是Object类提供,比较的是地址。所以需要覆写,String类的equals已经覆写过)

总结ArrayList:
1.ArrayList底层实现是对象数组(transient Object[ ] elementData;),声明一个ArrayList对象时,长度为0;
2.当数组长度不够用时,扩容策略变为原来数组的1.5倍;
3.对集合的增删改都是异步处理(没有锁),性能较高,线程不安全。

Vector类

package CODE.类集;

import java.util.List;
import java.util.Vector;

public class Vector1 {
    public static void main(String[] args) {
        List<String> list=new Vector<>();
        list.add("hai");
        list.add("pick");
        list.add("health");
        System.out.println(list);//[hai, pick, health]
        list.remove("pick");
        list.set(0,"hello");
        for(int i=0;i<list.size();i++)
        {
            System.out.println(list.get(i)); //hello health
        }
    }
}

Vector上的方法:

public synchronized E set(int index, E element)public synchronized boolean add(E e)public synchronized E get(int index)......

可以发现方法上都使用了内建锁。
总结:
1.Vector底层实现是对象数组( protected Object[] elementData;),声明一个Vector对象时,初始化对象长度为10 ;
2.当数组长度不够用时,扩容策略变为数组长度的2倍;
3.对集合的修改都采用同步处理(直接在方法上使用内建锁),性能较低,线程安全;

面试题:解释ArrayList与Vector区别。
1.产生版本:
Vector JDK1.0
ArrayList 1.2
2.线程安全:Vector采用在方法上添加synchronized来保证线程安全,性能较低,ArrayList采用异步处理,性能较高,线程不安全。(会引出synchronized优化或者其他锁等等)
3.初始化以及扩容策略:
Vector对象产生时就初始化数组 大小为10,当数组不够用时,扩容为原数组的2倍;
ArrayList使用懒加载策略,在第一次添加元素时才初始化数组大小,当数组不够用时,扩容为原数组的1.5倍。


linkedList子类

public class LinkedList<E>  extends AbstractSequentialList<E>

基于链表实现的动态数组。每当有新元素尾插。

面试题:解释ArrayList与LinkedList区别:
1.ArrayList里面存放的是数组,如果实例化此类对象时传入了数组大小,则
里面保存的数组就会开辟一个定长的数组,如果添加数据时,长度不够,在根据扩容策略动态扩1.5倍,所以在实际开发之中,使用ArrayList最好的做法就是设置初始化大小。ArrayList时间复杂度为1。
2.LinkedList是链表实现,每次需要尾插,LinkedList的复杂度为n。

Set接口(不允许重复元素,没有get与set)

Set接口中方法和父类接口Collection接口中方法一样 ,并没有对父类接口方法进行扩充。Set接口有2个常用子类:HashSet(无序存储),TreeSet(有序存储)

HashSet

HashSet基于哈希表实现,无序存储,通过计算哈希码实现,不允许重复元素,允许存放null,null有且只有一个。

package CODE.类集;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

//hashset ---无序存储,可以存放null,不允许重复元素
public class HashSet1 {
    public static void main(String[] args) {
        Set<String> set=new HashSet<>();
        set.add("pick");
        set.add("hello");
        set.add("hello");
        set.add(null);
        System.out.println(set);
    }
}

TreeSet

TreeSet基于红黑树实现,不允许重复元素,有序存储,并且按照元素升序排序,不允许存放null。

package CODE.类集;

import java.util.Set;
import java.util.TreeSet;

////TreeSet
//TreeSet基于红黑树实现,不允许重复元素,有序存储,并且按照元素升序排序,不允许存放null。
public class TreeSet1 {
    public static void main(String[] args) {
        Set<String> set=new TreeSet<>();
        set.add("Z");
        set.add("B");
        set.add("C");
        //set.add(null);//NullPointerException
        System.out.println(set);//[B, C, Z]
    }
}

猜你喜欢

转载自blog.csdn.net/sophia__yu/article/details/85077846