作者:~小明学编程
文章专栏:Java数据结构
格言:目之所及皆为回忆,心之所想皆为过往
目录
方法 | 解释 |
boolean add(E e) | 尾插 e |
void add(int index, E element) | 将 e 插入到 index 位置 |
boolean addAll(Collection extends E> c) | 尾插 c 中的元素 |
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(Object o) | 判断 o 是否在线性表中 |
int indexOf(Object o) | 返回第一个 o 所在下标 |
int lastIndexOf(Object o) | 返回最后一个 o 的下标 |
List | 截取部分 list |
- public static void main(String[] args) {
- ArrayList
lis = new ArrayList<>(); - lis.add("hello");
- lis.add("world");
- lis.add("!");
- lis.add("hello");
- System.out.println(lis);//[hello, world, !, hello]
- lis.add(2,"q");
- System.out.println(lis);//[hello, world, q, !, hello]
- lis.remove(1);
- System.out.println(lis);//[hello, q, !, hello]
- lis.remove("hello");
- System.out.println(lis);//[q, !, hello]
- }
方法 | 解释 |
ArrayList() | 无参构造 |
ArrayList(Collection extends E> c) | 利用其他 Collection 构建 ArrayList |
ArrayList(int initialCapacity) | 指定顺序表初始容量 |
如上表所示我们ArrayList()的构造方法一共有三种,第一种就是我们的无参构造,这种构造方法不用传参数直接new一个顺序表出来。
ArrayList lis = new ArrayList<>();
第二种就是有参数的构造方法我们传一个已有的顺序表。
- public static void main(String[] args) {
- ArrayList
lis = new ArrayList<>(); - lis.add("q");
- lis.add("w");
- ArrayList
lis1 = new ArrayList<>(lis); - System.out.println(lis1);//[q, w]
- }
第三种则是传参传一个initialCapacity也就是给我们的顺序表一个初始容量。
ArrayList lis = new ArrayList<>(10);
- ArrayList
lis = new ArrayList<>(); - System.out.println(lis.size());//0
我们可以看到当我们无参构造的时候我们顺序表的大小居然是0,那么顺表的大小是0的话就肯定不能去放元素进去,所以这中间肯定会进行一个扩容的。我们通过查看源码并分析得出了这样的一个结论。
如果ArrayList调用不带参数的构造方法,那么顺序表的大小初始为0,当第一次add的时候,整个顺序表的大小将会变成10,之后每次放满在不超过最大增容限制的时候就会进行1.5倍的扩容,如果给定容量的大小了,那么初始值就是给定的大小(不超过最大限制),之后每次满了之后还是进行1.5倍的扩容。
1.直接打印
System.out.println(lis);//toString方法打印
2.fori遍历
- for (int i=0;i < lis.size();i++) {
- System.out.println(lis.get(i));
- }
通过我们的get()方法依次获取指定下标的元素进行打印。
3.forreach遍历
- for (String ret: lis) {
- System.out.println(ret);
- }
4.迭代器打印
- //迭代器打印
- Iterator
it = lis.iterator(); - while(it.hasNext()) {
- System.out.println(it.next());
- }
- //迭代器list相关打印
- ListIterator it2 = lis.listIterator();
- while(it.hasNext()) {
- System.out.println(it2.next());
- }
public interface ListIterator extends Iterator
这是我们点开的源码我们可以看到 ListIterator
注意事项:
在我们使用Iterator的时候remove()之前必须得有next(),不能让迭代器在同一个位置remove()两次,否则的话将会抛出以下的异常。
- Iterator
it = lis.iterator(); - while(it.hasNext()) {
- it.remove();
- System.out.println(it.next());
- }
Exception in thread "main" java.lang.IllegalStateException
所以我们想要删除集合中某一个元素的时候我们需要先next()迭代出当前的元素,然后再对其进行一个remove()。
正确的写法如下:
- Iterator
it = lis.iterator(); - while(it.hasNext()) {
- String ret = it.next();
- if (ret.equals("hello")) {
- it.remove();
- } else {
- System.out.println(ret);
- }
- }
———————————————————————————————————————————
利用迭代器在读取的时候插入数据:
- ListIterator
it2 = lis.listIterator(); - System.out.println("============");
- while(it2.hasNext()) {
- String ret = it2.next();
- if (ret.equals("hello")) {
- it2.add("hahaha");
- } else {
- System.out.println(ret);
- }
- }
- System.out.println("===============^");
- System.out.println(lis);//[q, !, hello, hahaha]
值得注意的是我们的迭代器在读取的时候是可以it2.add,但是不能lis.add(),因为我们的ArrayList是单线程的属于线程不安全的,否则的话将会抛出异常。
- class MyArrayList
{ - private Object[] elementData;//数组
- private int useSize;//有效的数据个数
- private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//默认的空数组
- //不带参数的构造方法
- public MyArrayList () {
- this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
- }
- //带参数的构造方法
- public MyArrayList (int capacity) {
- if (capacity>0) {
- this.elementData = new Object[capacity];
- } else if (capacity==0) {
- this.elementData = new Object[0];
- } else {
- throw new IllegalArgumentException("初始容量小于0了");
- }
- }
- public boolean add (E e) {
- //确定一个真正的容量,判断一波是否需要扩容
- ensureCapacityInternal(useSize + 1);
- //现在可以放心的向里面放元素了
- elementData[useSize++] = e;
- return true;
- }
- public void add(int index,E e) {
- rangeCheckForAdd(index);
- ensureCapacityInternal(useSize+1);
- copy(index,e);//拷贝数组
- useSize++;
- }
- public int size() {
- return useSize;
- }
- private void copy(int index,E e) {
- for(int i=useSize-1;i>=index;i--) {
- elementData[i+1] = elementData[i];
- }
- elementData[index] = e;
- }
-
- private void rangeCheckForAdd(int index) {
- if (index > size() || index < 0)
- throw new IndexOutOfBoundsException("index的位置不合法!");
- }
- private void ensureCapacityInternal(int minCapacity) {
- //计算得出分析之后的容量
- int capacity = calculateCapacity(elementData,minCapacity);
- ensureExplicitCapacity(capacity);
-
- }
- private void ensureExplicitCapacity(int minCapacity) {
- // 若分析之后的容量大于当前的容量则开始扩容
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }
- private static int MAX_ARRAY_SIZE = Integer.MAX_VALUE-8;
- private void grow(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = elementData.length;
- //确定新的容量的大小
- int newCapacity = oldCapacity + (oldCapacity >> 1);//扩大1.5倍
- 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);
- }
- private static int hugeCapacity(int minCapacity) {
- if (minCapacity < 0) // overflow
- throw new OutOfMemoryError();
- return (minCapacity > MAX_ARRAY_SIZE) ?
- Integer.MAX_VALUE :
- MAX_ARRAY_SIZE;
- }
- private static int calculateCapacity(Object[] elementData, int minCapacity) {
- if (elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//如果没有分配过大小
- return Math.max(10,minCapacity);//返回一个10
- }
- return minCapacity;
- }
-
- }
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
-
- //扑克牌类
- class Card {
- private int rank;//数字
- private String suit;//花色
-
- public Card(int rank, String suit) {
- this.rank = rank;
- this.suit = suit;
- }
-
- @Override
- public String toString() {
- return "[ "+this.suit+" "+this.rank+" ]";
- }
- }
- public class Test {
- private static final String[] suits = {"♥","♠","♣","♦"};//花色数组
- //买牌
- public static List
buyCard() { - //new一个顺序表用于存放我们的Card,这边给一个初始值因为我们已只牌的数量
- List
lis = new ArrayList<>(52); - for (int i = 0; i < 4; i++) {
- for (int j = 1; j <= 13; j++) {
- String suit = suits[i];
- int rank = j;
- Card card = new Card(rank,suit);
- lis.add(card);
- }
- }
- return lis;
- }
- //交换两个位置的牌
- private static void swap(List
cards,int i,int j) { - Card card = cards.get(i);
- cards.set(i,cards.get(j));
- cards.set(j,card);
- }
- //定义一个洗牌的方法
- public static void shuffle(List
cards) { - int size = cards.size();
- for (int i = size-1;i>0;i--) {
- Random random = new Random();
- int rand = random.nextInt(i);
- swap(cards,i,rand);
- }
- }
- public static void main(String[] args) {
- System.out.println("买牌中");
- List
cards = buyCard(); - System.out.println("洗牌中");
- shuffle(cards);
- System.out.println("开始发牌");
- ArrayList
> hand = new ArrayList<>();
- List
hand1 = new ArrayList<>(); - List
hand2 = new ArrayList<>(); - List
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++) {
- hand.get(j).add(cards.remove(0));
- }
- }
- System.out.println("第1个人的牌"+hand1);
- System.out.println("第2个人的牌"+hand2);
- System.out.println("第3个人的牌"+hand3);
- System.out.println("剩余的牌"+cards);
-
- }
- public static void main1(String[] args) {
- Card card = new Card(7,"♥");
- System.out.println(card.toString());
- }
- }