赞
踩
目录
二、ArrayList源码介绍(动态扩容以及构造方法是如何实现的)
注:List subList(int fromIndex, int toIndex):
List subList(int fromIndex, int toIndex)方法的演示:
常见的线性表结构:顺序表,链表,栈,队列。(线性表在逻辑上是线性结构,也就是一条线,但是在物理结构上不一定是连续的,通常是以数组和链表的形式存储)
顺序表:用一段物理地址连续的存储空间来存储数据元素,一般采用数组存储。
在集合框架中,ArrayList是一个类,实现了List接口:
1. ArrayList是以泛型的方式实现的,使用时必须先实例化 |
2. ArrayList实现了randomAccess接口,所以ArrayList支持随机访问 |
3. ArrayList实现了Cloneable接口,ArrayList时可以克隆的 |
4. ArrayList不是线程安全的,(Vector是线程安全的) |
5. ArrayList是一段连续的空间,可以动态扩容,是动态的顺序表 |
- public static void main(String[] args) {
- ArrayList<Integer> arrayList = new ArrayList<>();
- arrayList.add(1);
- }
- public ArrayList() {
- this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
- }
-
- private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
如下代码;当我们new一个ArrayList数组的时候,我们可以看到ArrayList的源码,此时并没有开辟一块内存空间,而是new了一个空的数组,所以应该是在add第一个数据元素的时候开辟的空间,我们需要再看一下add() 方法的源码:
- public boolean add(E e) {
- ensureCapacityInternal(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
-
- private void ensureCapacityInternal(int minCapacity) {
- ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
- }
-
- private static int calculateCapacity(Object[] elementData, int minCapacity) {
- if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
- return Math.max(DEFAULT_CAPACITY, minCapacity);
- }
- return minCapacity;
- }
-
- private void ensureExplicitCapacity(int minCapacity) {
- modCount++;
-
- // overflow-conscious code
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }
- private void grow(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = elementData.length;
- int newCapacity = oldCapacity + (oldCapacity >> 1);
- if (newCapacity - minCapacity < 0)
- newCapacity = minCapacity;
- if (newCapacity - MAX_ARRAY_SIZE > 0)
- newCapacity = hugeCapacity(minCapacity);
- // minCapacity is usually close to size, so this is a win:
- elementData = Arrays.copyOf(elementData, newCapacity);
- }
ArrayList( ) | 无参数构造 |
ArrayList(Collection<? extends E> c) | 只要实现了Collection接口的类都可以作为这个构造方法的参数 |
ArrayList(int initialCapacity) | 指定顺序表初始容量 |
- public static void main(String[] args) {
- //无参构造,在第一次add元素时给初始容量大小是10,扩容按1.5倍扩容
- ArrayList<Integer> arrayList = new ArrayList<>();
- arrayList.add(1);
- arrayList.add(2);
- //可以传参一个实现了Collection接口的类的实例化对象
- LinkedList<Integer> linkedList = new LinkedList<>();
- //可以传参一个具体的对象,之后这个ArrayList1数组就包含了这个LinkedList中的数据
- ArrayList<Integer> arrayList1 = new ArrayList<>(linkedList);
- //带一个参数的构造:这个参数多大,这个数组的初始化容量就是多大
- ArrayList<Integer> arrayList2 = new ArrayList<>(20);
- }
boolean add(E e) | 尾插e |
void add(int index, E element) | 将e插入index位置 |
boolean addAll(Collection<? extends E> c) | 尾插c中的元素(c类型只要是实现了Collection接口即可) |
E remove(int index) | 删除index位置元素 |
boolean remove(Object o) | 删除遇到的第一个o(也就是参数可以传一个下标,也可以传一个具体的对象) |
E get(int index) | 获取下标index位置的元素 |
E set(int index, E element) | 将下标index位置元素设置为element |
void clear() | 清空数组中的元素 |
boolean contains(Objec o) | 判断o是否在线性表中 |
List<E> subList(int fromIndex, int toIndex) | 截取部分list |
1. 这个方法返回值必须是List接口,泛型参数也要匹配 |
2. from to(下标),此时这个区间是左闭右开的 |
3. 调用subList方法之后,此时没有new一个新的对象,只是将截取部分list的首地址给了这个方法的返回值 |
- public static void main(String[] args) {
- List<Integer> list = new ArrayList<>();
- list.add(1);//尾插元素e,默认放在数组的最后的位置
- list.add(2);
- list.add(3);
- LinkedList<Integer> linkedList = new LinkedList<>();
- linkedList.add(4);
- linkedList.add(5);
- list.addAll(linkedList);//将linkedList中的元素放进list中
- System.out.println(list);
- list.get(2);
- list.set(2,222);
- boolean a = list.contains(222);
- System.out.println(a);
- List<Integer> list1 = list.subList(1,4);//此时截取的是下标1-3位置的元素
- System.out.println(list1);
- list1.remove(2);
- list1.remove(new Integer(222));
- System.out.println(list1);
- //清空数组中的元素
- list.clear();
- System.out.println(list);
- }
- List<Integer> list = new ArrayList<>();
- list.add(1);//尾插元素e,默认放在数组的最后的位置
- list.add(2);
- list.add(3);
- LinkedList<Integer> linkedList = new LinkedList<>();
- linkedList.add(4);
- linkedList.add(5);
- List<Integer> list1 = list.subList(1,3);
- list1.set(0,1111);
- System.out.println(list1);
- System.out.println(list);
运行结果:
此时可以看到将截取之后的list1中的下标1位置的元素改变之后,原来list中的元素也跟着一块改变了,此时就说明截取的对象并没有产生新的对象,只是将截取后的列表的首地址给到了subList方法的返回值。
1. 直接打印输出,因为在父类AbstractCollection中重写了toString()方法 |
2. for循环遍历数组中的元素 |
3. for each循环遍历数组中的元素 |
4. Iterator迭代器循环遍历数组中的元素 |
- public static void main(String[] args) {
- //无参构造,在第一次add元素时给初始容量大小是10,扩容按1.5倍扩容
- List<Integer> arrayList = new ArrayList<>();
- arrayList.add(1);
- arrayList.add(2);
- arrayList.add(3);
- //直接遍历:在AbstractCollection中重写了toString方法
- System.out.println(arrayList);
-
- //for循环遍历
- for (int i = 0; i < arrayList.size(); i++) {
- System.out.print(arrayList.get(i) + " ");
- }
- //for each遍历
- System.out.println();
- for (Integer x : arrayList) {
- System.out.print(x + " ");
- }
- //迭代器的遍历
- Iterator<Integer> it = arrayList.listIterator();
- while (it.hasNext()) {
- System.out.println(it.next() + " ");
- }
- }
- package PokerGame;
-
- public class Poker {
- //定义花色
- private String suit;
- //数字
- private int rank;
- public Poker(String suit, int rank) {
- this.suit = suit;
- this.rank = rank;
- }
- public String getSuit() {
- return suit;
- }
- public void setSuit(String suit) {
- this.suit = suit;
- }
- public int getRank() {
- return rank;
- }
- public void setRank(int rank) {
- this.rank = rank;
- }
- @Override
- public String toString() {
- return "{" + suit + " " + rank + "}";
- }
- }
- package PokerGame;
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
-
- public class Game {
- private static final String[] suits = {"♥", "♣", "♦", "♠"};
- public List<Poker> buyPoker() {
- List<Poker> pokers = new ArrayList<>();
- //每一张Poker都需要有四种颜色
- for (int i = 0; i < 4; i++) {
- //每一种颜色都需要生成13张牌
- for (int j = 1; j <= 13; j++) {
- Poker poker = new Poker(suits[i],j);
- pokers.add(poker);
- }
- }
- return pokers;
- }
- public void shuffle(List<Poker> pokers) {
- for (int i = pokers.size() - 1; i > 0; i--) {
- Random random = new Random();
- int index = random.nextInt(i);//这里就是生成一个0-51的随机数
- //交换: 生成一个随机数,从最后一张牌开始和前边的牌交换
- swap(pokers,i,index);
- }
- }
- private void swap(List<Poker> pokers,int i, int j) {
- Poker tmp = pokers.get(i);
- pokers.set(i,pokers.get(j));//这里调用的是List的set方法
- pokers.set(j,tmp);
- }
- public List<List<Poker>> game(List<Poker> pokers) {
- List<List<Poker>> hand = new ArrayList<>();
- List<Poker> hand1 = new ArrayList<>();
- List<Poker> hand2 = new ArrayList<>();
- List<Poker> hand3 = new ArrayList<>();
- hand.add(hand1);
- hand.add(hand2);
- hand.add(hand3);
- //最外层循环 控制轮数
- for (int i = 0; i < 5; i++) {
- for (int j = 0; j < 3; j++) {
- Poker removePoker = pokers.remove(0);
- hand.get(j).add(removePoker);
- }
- }
- return hand;
- }
- }
- package PokerGame;
-
- import java.util.List;
-
- public class Text {
- public static void main(String[] args) {
- Game game = new Game();
- List<Poker> pokers = game.buyPoker();
- System.out.println(pokers);
- //洗牌
- System.out.println("洗牌:");
- game.shuffle(pokers);
- //
- System.out.println(pokers);
-
- //揭牌:
- List<List<Poker>> hand = game.game(pokers);
- System.out.println("揭牌:");
- for (int i = 0; i < hand.size(); i++) {
- System.out.println("第"+(i+1)+"个人的牌:"+hand.get(i));
- }
- //剩下的牌
- System.out.println(pokers);
- }
- }
- //杨辉三角
- public List<List<Integer>> generate(int numRows) {
- List<List<Integer>> ret = new ArrayList<>();
- List<Integer> row = new ArrayList<>();
- row.add(1);
- ret.add(row);
- for (int i = 1; i < numRows; i++) {//i就是行的下标
- List<Integer> prevRow = ret.get(i-1);
- List<Integer> curRow = new ArrayList<>();
- curRow.add(1);//第一个1
- //中间的数值
- for (int j = 1; j < i; j++) {//j就是列的下标
- int x = prevRow.get(j) + prevRow.get(j - 1);
- curRow.add(x);
- }
- curRow.add(1);
- ret.add(curRow);
- }
- return ret;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。