一:什么是类集
从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.在第一次add时,由于数组为空,将默认10和1(size+1=0+1=1)比较,选一个较大值,数组先扩容成10个,当数组长度不够用时,扩容策略变为原来数组长度的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使用懒加载策略,在第一次添加元素时才初始化数组大小为10个,当数组不够用时,扩容为原数组的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]
}
}