Java集合重点讲解1:ArrayList、Vector和Stack

集合

 

数组是一个容器,存储一组数据类型一致且长度固定的元素。数组有长度的限制,而通过一些数据结构的操作,如链表,可以完成动态对象数组的操作。

集合也是一个容器,与数组类似,但集合的长度存储之后可以改变。所谓的类集就是一个个动态的对象数组,是对一些实现好的数据结构进行了包装,类集框架本身不受数组长度的限制。

类集框架主要接口之间的继承关系:

一、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)

持续更新中......

下一篇:Java集合重点讲解2:LinkedList、Queue、Iterator、fail-fast机制

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值