当前位置:   article > 正文

Java集合框架:ArrayList详解

arraylist

目录

一、ArrayList简介

二、ArrayList源码介绍(动态扩容以及构造方法是如何实现的)

1. 扩容机制:

  源码:

  源码详解: ​编辑

  如何扩容:

  2. 扩容源码详解:

 三、ArrayList的构造方法

    构造方法的演示:

四、ArrayList类的常用方法

             注:List subList(int fromIndex, int toIndex):

    常用的方法演示:

    List subList(int fromIndex, int toIndex)方法的演示:

五、ArrayList的几种遍历方式

、ArrayList练习

   1. 实现洗牌算法

    2. 杨辉三角


     ​​​常见的线性表结构:顺序表,链表,栈,队列。(线性表在逻辑上是线性结构,也就是一条线,但是在物理结构上不一定是连续的,通常是以数组和链表的形式存储)

     顺序表:用一段物理地址连续的存储空间来存储数据元素,一般采用数组存储。

一、ArrayList简介

    在集合框架中,ArrayList是一个类,实现了List接口:

1. ArrayList是以泛型的方式实现的,使用时必须先实例化

2. ArrayList实现了randomAccess接口,所以ArrayList支持随机访问

3. ArrayList实现了Cloneable接口,ArrayList时可以克隆的
4. ArrayList不是线程安全的,(Vector是线程安全的)
5. ArrayList是一段连续的空间,可以动态扩容,是动态的顺序表

二、ArrayList源码介绍(动态扩容以及构造方法是如何实现的)

1. 扩容机制:

  1. public static void main(String[] args) {
  2. ArrayList<Integer> arrayList = new ArrayList<>();
  3. arrayList.add(1);
  4. }

  源码:

  1. public ArrayList() {
  2. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  3. }
  4. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    如下代码;当我们new一个ArrayList数组的时候,我们可以看到ArrayList的源码,此时并没有开辟一块内存空间,而是new了一个空的数组,所以应该是在add第一个数据元素的时候开辟的空间,我们需要再看一下add() 方法的源码:

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + 1); // Increments modCount!!
  3. elementData[size++] = e;
  4. return true;
  5. }
  6. private void ensureCapacityInternal(int minCapacity) {
  7. ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  8. }
  9. private static int calculateCapacity(Object[] elementData, int minCapacity) {
  10. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  11. return Math.max(DEFAULT_CAPACITY, minCapacity);
  12. }
  13. return minCapacity;
  14. }
  15. private void ensureExplicitCapacity(int minCapacity) {
  16. modCount++;
  17. // overflow-conscious code
  18. if (minCapacity - elementData.length > 0)
  19. grow(minCapacity);
  20. }

   源码详解:

 如何扩容:

  1. private void grow(int minCapacity) {
  2. // overflow-conscious code
  3. int oldCapacity = elementData.length;
  4. int newCapacity = oldCapacity + (oldCapacity >> 1);
  5. if (newCapacity - minCapacity < 0)
  6. newCapacity = minCapacity;
  7. if (newCapacity - MAX_ARRAY_SIZE > 0)
  8. newCapacity = hugeCapacity(minCapacity);
  9. // minCapacity is usually close to size, so this is a win:
  10. elementData = Arrays.copyOf(elementData, newCapacity);
  11. }

  2. 扩容源码详解:

 三、ArrayList的构造方法

ArrayList( )无参数构造
ArrayList(Collection<? extends E> c)只要实现了Collection接口的类都可以作为这个构造方法的参数
ArrayList(int initialCapacity)指定顺序表初始容量

    构造方法的演示:

  1. public static void main(String[] args) {
  2. //无参构造,在第一次add元素时给初始容量大小是10,扩容按1.5倍扩容
  3. ArrayList<Integer> arrayList = new ArrayList<>();
  4. arrayList.add(1);
  5. arrayList.add(2);
  6. //可以传参一个实现了Collection接口的类的实例化对象
  7. LinkedList<Integer> linkedList = new LinkedList<>();
  8. //可以传参一个具体的对象,之后这个ArrayList1数组就包含了这个LinkedList中的数据
  9. ArrayList<Integer> arrayList1 = new ArrayList<>(linkedList);
  10. //带一个参数的构造:这个参数多大,这个数组的初始化容量就是多大
  11. ArrayList<Integer> arrayList2 = new ArrayList<>(20);
  12. }

四、ArrayList类的常用方法

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

    注:List<E> subList(int fromIndex, int toIndex):

1. 这个方法返回值必须是List接口,泛型参数也要匹配 
2. from to(下标),此时这个区间是左闭右开的
3. 调用subList方法之后,此时没有new一个新的对象,只是将截取部分list的首地址给了这个方法的返回值

   常用的方法演示:

  1. public static void main(String[] args) {
  2. List<Integer> list = new ArrayList<>();
  3. list.add(1);//尾插元素e,默认放在数组的最后的位置
  4. list.add(2);
  5. list.add(3);
  6. LinkedList<Integer> linkedList = new LinkedList<>();
  7. linkedList.add(4);
  8. linkedList.add(5);
  9. list.addAll(linkedList);//将linkedList中的元素放进list中
  10. System.out.println(list);
  11. list.get(2);
  12. list.set(2,222);
  13. boolean a = list.contains(222);
  14. System.out.println(a);
  15. List<Integer> list1 = list.subList(1,4);//此时截取的是下标1-3位置的元素
  16. System.out.println(list1);
  17. list1.remove(2);
  18. list1.remove(new Integer(222));
  19. System.out.println(list1);
  20. //清空数组中的元素
  21. list.clear();
  22. System.out.println(list);
  23. }

 List<E> subList(int fromIndex, int toIndex)方法的演示:

  1. List<Integer> list = new ArrayList<>();
  2. list.add(1);//尾插元素e,默认放在数组的最后的位置
  3. list.add(2);
  4. list.add(3);
  5. LinkedList<Integer> linkedList = new LinkedList<>();
  6. linkedList.add(4);
  7. linkedList.add(5);
  8. List<Integer> list1 = list.subList(1,3);
  9. list1.set(0,1111);
  10. System.out.println(list1);
  11. System.out.println(list);

  运行结果:

      此时可以看到将截取之后的list1中的下标1位置的元素改变之后,原来list中的元素也跟着一块改变了,此时就说明截取的对象并没有产生新的对象,只是将截取后的列表的首地址给到了subList方法的返回值。

五、ArrayList的几种遍历方式

1. 直接打印输出,因为在父类AbstractCollection中重写了toString()方法

2. for循环遍历数组中的元素

3. for each循环遍历数组中的元素
4. Iterator迭代器循环遍历数组中的元素
  1. public static void main(String[] args) {
  2. //无参构造,在第一次add元素时给初始容量大小是10,扩容按1.5倍扩容
  3. List<Integer> arrayList = new ArrayList<>();
  4. arrayList.add(1);
  5. arrayList.add(2);
  6. arrayList.add(3);
  7. //直接遍历:在AbstractCollection中重写了toString方法
  8. System.out.println(arrayList);
  9. //for循环遍历
  10. for (int i = 0; i < arrayList.size(); i++) {
  11. System.out.print(arrayList.get(i) + " ");
  12. }
  13. //for each遍历
  14. System.out.println();
  15. for (Integer x : arrayList) {
  16. System.out.print(x + " ");
  17. }
  18. //迭代器的遍历
  19. Iterator<Integer> it = arrayList.listIterator();
  20. while (it.hasNext()) {
  21. System.out.println(it.next() + " ");
  22. }
  23. }

六、ArrayList练习

   1. 实现洗牌算法

  1. package PokerGame;
  2. public class Poker {
  3. //定义花色
  4. private String suit;
  5. //数字
  6. private int rank;
  7. public Poker(String suit, int rank) {
  8. this.suit = suit;
  9. this.rank = rank;
  10. }
  11. public String getSuit() {
  12. return suit;
  13. }
  14. public void setSuit(String suit) {
  15. this.suit = suit;
  16. }
  17. public int getRank() {
  18. return rank;
  19. }
  20. public void setRank(int rank) {
  21. this.rank = rank;
  22. }
  23. @Override
  24. public String toString() {
  25. return "{" + suit + " " + rank + "}";
  26. }
  27. }
  1. package PokerGame;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Random;
  5. public class Game {
  6. private static final String[] suits = {"♥", "♣", "♦", "♠"};
  7. public List<Poker> buyPoker() {
  8. List<Poker> pokers = new ArrayList<>();
  9. //每一张Poker都需要有四种颜色
  10. for (int i = 0; i < 4; i++) {
  11. //每一种颜色都需要生成13张牌
  12. for (int j = 1; j <= 13; j++) {
  13. Poker poker = new Poker(suits[i],j);
  14. pokers.add(poker);
  15. }
  16. }
  17. return pokers;
  18. }
  19. public void shuffle(List<Poker> pokers) {
  20. for (int i = pokers.size() - 1; i > 0; i--) {
  21. Random random = new Random();
  22. int index = random.nextInt(i);//这里就是生成一个0-51的随机数
  23. //交换: 生成一个随机数,从最后一张牌开始和前边的牌交换
  24. swap(pokers,i,index);
  25. }
  26. }
  27. private void swap(List<Poker> pokers,int i, int j) {
  28. Poker tmp = pokers.get(i);
  29. pokers.set(i,pokers.get(j));//这里调用的是List的set方法
  30. pokers.set(j,tmp);
  31. }
  32. public List<List<Poker>> game(List<Poker> pokers) {
  33. List<List<Poker>> hand = new ArrayList<>();
  34. List<Poker> hand1 = new ArrayList<>();
  35. List<Poker> hand2 = new ArrayList<>();
  36. List<Poker> hand3 = new ArrayList<>();
  37. hand.add(hand1);
  38. hand.add(hand2);
  39. hand.add(hand3);
  40. //最外层循环 控制轮数
  41. for (int i = 0; i < 5; i++) {
  42. for (int j = 0; j < 3; j++) {
  43. Poker removePoker = pokers.remove(0);
  44. hand.get(j).add(removePoker);
  45. }
  46. }
  47. return hand;
  48. }
  49. }
  1. package PokerGame;
  2. import java.util.List;
  3. public class Text {
  4. public static void main(String[] args) {
  5. Game game = new Game();
  6. List<Poker> pokers = game.buyPoker();
  7. System.out.println(pokers);
  8. //洗牌
  9. System.out.println("洗牌:");
  10. game.shuffle(pokers);
  11. //
  12. System.out.println(pokers);
  13. //揭牌:
  14. List<List<Poker>> hand = game.game(pokers);
  15. System.out.println("揭牌:");
  16. for (int i = 0; i < hand.size(); i++) {
  17. System.out.println("第"+(i+1)+"个人的牌:"+hand.get(i));
  18. }
  19. //剩下的牌
  20. System.out.println(pokers);
  21. }
  22. }

    2. 杨辉三角

  1. //杨辉三角
  2. public List<List<Integer>> generate(int numRows) {
  3. List<List<Integer>> ret = new ArrayList<>();
  4. List<Integer> row = new ArrayList<>();
  5. row.add(1);
  6. ret.add(row);
  7. for (int i = 1; i < numRows; i++) {//i就是行的下标
  8. List<Integer> prevRow = ret.get(i-1);
  9. List<Integer> curRow = new ArrayList<>();
  10. curRow.add(1);//第一个1
  11. //中间的数值
  12. for (int j = 1; j < i; j++) {//j就是列的下标
  13. int x = prevRow.get(j) + prevRow.get(j - 1);
  14. curRow.add(x);
  15. }
  16. curRow.add(1);
  17. ret.add(curRow);
  18. }
  19. return ret;
  20. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/766374
推荐阅读
相关标签
  

闽ICP备14008679号