集合
数组是一个容器,存储一组数据类型一致且长度固定的元素。数组有长度的限制,而通过一些数据结构的操作,如链表,可以完成动态对象数组的操作。
集合也是一个容器,与数组类似,但集合的长度存储之后可以改变。所谓的类集就是一个个动态的对象数组,是对一些实现好的数据结构进行了包装,类集框架本身不受数组长度的限制。
类集框架主要接口之间的继承关系:
一、ArrayList
概述
ArrayList底层是一个数组,所属java.util包,是实现List接口的动态数组。
ArrayList的定义(源码跟踪):
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public abstract class AbstractList<E>
extends AbstractCollection<E> implements List<E>
由于ArrayList底层是一个Object[]数组, 什么类型都可以存进去,取出来的时候是多态的效果,需要自己造型,麻烦,JDK1.5之后,使用了泛型,解决了这个问题。
附:泛型可以使用在类、接口、方法中。
ArrayList实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。所以为了保证同步,最好的办法是在创建时完成,以防止意外对列表进行不同步的访问:
List list = Collections.synchronizedList(new ArrayList(...));
ArrayList底层是一个Object[]数组
transient Object[] elementData; // non-private to simplify nested class access
增加:add()
实例:ArrayList可以双向输出
public class ArrayListDemo1 {
public static void main(String[] args) {
List<String> allList = new ArrayList<String>();
allList.add("I");
allList.add("am");
allList.add("Mona");
allList.add(0, "Hi ");
System.out.println("由前向后输出:");
for(int i=0; i<allList.size(); i++) {//循环输出集合内容
System.out.print(allList.get(i) + " ");
}
System.out.println("\n由后向前输出:");
for(int i=allList.size()-1; i>=0;i--) {
System.out.print(allList.get(i) + " ");
}
}
}
输出:
由前向后输出:
Hi I am Mona
由后向前输出:
Mona am I Hi
删除:remove
public class ArrayListDemo1 {
public static void main(String[] args) {
List<String> allList = new ArrayList<String>();
allList.add("I");
allList.add("am");
allList.add("Mona");
allList.add(0, "Hi ");
allList.remove(0);
for(int i=0; i<allList.size(); i++) {
System.out.print(allList.get(i) + " ");
}
}
}
输出:
I am Mona
toString()方式输出
public class ArrayListDemo1 {
public static void main(String[] args) {
List<String> allList = new ArrayList<String>();
allList.add("I");
allList.add("am");
allList.add("Mona");
allList.add(0, "Hi ");
System.out.println(allList);
}
}
输出为:
[Hi , I, am, Mona]
扩容
初始容量为:10
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
扩容为原来的1.5倍
//添加一个元素,则size加一
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//初始化
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//size是当前集合拥有的元素个数(未算进准备新增的e元素),从源码看出,调用了
//ensureCapacityInternal来保证容量问题,传进去的参数是size+1,来保证新增元素后容量满足要求
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
//扩容
//如果minCapacity小于10的话(如果elementData为空的话,size+1即minCapacity一般为1),
//返回10,所以如果没有指定大小,默认是初始化一个容量为10的数组
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
将集合变为对象数组
public class ArrayListDemo2 {
public static void main(String[] args) {
List<String> allList = new ArrayList<String>();
allList.add("I");
allList.add("am");
allList.add("Mona");
allList.add(0, "Hi ");
String[] str = allList.toArray(new String[] {});//指定泛型类型(使用匿名对象)
System.out.print("指定数组类型:");
for(int i=0; i<str.length; i++) {
System.out.print(str[i] + "、");
}
System.out.print("\n返回对象数组:");
Object[] obj = allList.toArray();//直接返回对象数组
for(int i=0; i<obj.length; i++) {
String temp = (String) obj[i];//每一个对象都是String类型实例
System.out.print(temp + "、");
}
}
}
输出:
指定数组类型:Hi 、I、am、Mona、
返回对象数组:Hi 、I、am、Mona、
二、Vector
概述
Vector所属的包为:java.util
是ArrayList集合的早期版本(StringBuffer早期,StringBuilder后期)
Vector底层也是利用(动态)数组的形式存储
Vector是线程同步的(synchronized) 安全性高 但是同时效率低
继承关系:
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
底层是Object[]数组
protected Object[] elementData;
例子:
public class ArrayListDemo3 {
public static void main(String[] args) {
List<String> allList = new Vector<String>();
allList.add("I");
allList.add("am");
allList.add("Mona");
allList.add(0, "Hi ");
for(int i=0; i<allList.size(); i++) {
System.out.print(allList.get(i) + " ");
}
}
}
其他类比ArrayList
扩容方式
与ArrayList不同,默认扩容2倍,可以通过构造方法创建对象时修改这一机制
/**
* Constructs an empty vector so that its internal data array
* has size {@code 10} and its standard capacity increment is
* zero.
*/
public Vector() {
this(10);
}
ArrayList和Vector的主要区别
ArrayList是在JDK1.2之后推出的,属于新的操作类
性能:采用异步处理方式,性能更高
线程安全:属于非线程安全的操作类
输出:只能用Iterator、foreach输出
Vector是在JDK1.0时推出,属于旧的操作类
性能:采用同步处理方式,性能较低
线程安全:属于线程安全的操作类
输出:可以使用Iterator、foreach、Enumeration输出
三、Stack
概述
Stack(栈)----先入后出
所属的包为java.util
继承自Vector
除了继承自Vactor类的方法外,还有特殊的方法
push():压入栈顶
pop():弹出,即从栈顶取出并删除
peek():查看栈顶的一个元素
boolean = empty():判断栈内元素是否为空
int = search()查找给定的元素在栈中的位置(indexOf())
联想:中国象棋---->毁棋
public
class Stack<E> extends Vector<E> {
//只有一个空的构造方法
public Stack() {
}
public E push(E item) {
addElement(item);
return item;
}
//加锁了---线程安全
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
public boolean empty() {
return size() == 0;
}
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
由于Stack基于Vector,详情请移步前方Vector部分
例子:
public class StackDemo {
public static void main(String[] args) {
Stack<String> s = new Stack<String>();
s.push("A");
s.push("B");
s.push("C");
System.out.println(s.pop());//正常出栈
System.out.println(s.pop());//正常出栈
System.out.println(s.pop());//正常出栈
System.out.println(s.pop());//错误,栈为空,出现异常
}
}
输出:
C
B
A
Exception in thread "main" java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at java.util.Stack.pop(Stack.java:84)
at test2.StackDemo.main(StackDemo.java:14)
持续更新中......