java--ArrayList

ArrayList

1.ArrayList简介

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:
java--ArrayList_第1张图片
【说明】

  1. ArrayList是以泛型方式实现的,使用时必须要先实例化
  2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
  3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
  4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
  5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
  6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序

2.ArrayList构造

1.无参构造

public static void main(String[] args)
    {
        List<String> list=new ArrayList<>();//调用了不带参数的构造方法
        list.add("hello");
        //总结:当调用不带参数的构造方法的时候,底层的数组长度为0,但是当我第一次add的时候
        //才会为我分配内存,此时第一次分配的内存为10
        //扩容的方法(grwo),每次1.5倍扩容

    }

2.利用其他Collection构建ArrayList

 	 public static void main(String[] args)
    {
        ArrayList<String> arrayList1=new ArrayList<>();
        arrayList1.add("abc");
        arrayList1.add("def");
        List<String> list1=new ArrayList<>(arrayList1);

        ArrayList<Integer> arrayList2=new ArrayList<>();
        List<String> list2=new ArrayList<>(arrayList2);

    }

java--ArrayList_第2张图片
list2会出错
原因是
ArrayList底层的构造方法是这样的

java--ArrayList_第3张图片
上面这段代码结合图片来看,list1传入的arrlist1的类型是String,跟List的类型一样,符合
arrlist2的类型是Integer,不符合,所以报错
这里的String,Integer相当于E
java--ArrayList_第4张图片

class Person
{

}
class Student extends Person
{

}
 public static void main(String[] args)
    {
        ArrayList<Student> arrayList1=new ArrayList<>();
        List<Person> list=new ArrayList<>(arrayList1);

    }

arrayList1的类型是Student,传入list1里面,list1的类型是Person,而arrayList1的Student类型是Person的子类,所以不会报错

3.ArrayList常见操作

ArrayList虽然提供的方法比较多,但是常用方法如下所示,需要用到其他方法时,同学们自行查看ArrayList的帮助文档。
java--ArrayList_第5张图片
这里拿几个举例
1.addAll

    public static void main(String[] args) {
        ArrayList<String> arrayList=new ArrayList<>();
        arrayList.add("abc");
        arrayList.add("def");
        arrayList.add("wwww");
        List<String> list=new ArrayList<>();//向上转型
        //List是ArrayList的父类,所以list可以调用add和addALL
        list.add("hello");
        list.addAll(arrayList);
        System.out.println(list.toString());
    }

在这里插入图片描述
2.remove

		String ret=list.remove(0);
        System.out.println(list.toString());

在这里插入图片描述

 		boolean ret2=list.remove("abc");//删除成功就是true,否则false
        System.out.println(list.toString());

在这里插入图片描述
3.clear
数组长度变为0了
在这里插入图片描述

java--ArrayList_第6张图片
4.subList

	public static void main(String[] args)
    {
        ArrayList<String> arrayList=new ArrayList<>();
        arrayList.add("abc");
        arrayList.add("def");
        arrayList.add("wwww");
        arrayList.add("qaaaaaaa");
        arrayList.add("ddddddddddd");
        List<String> ret = arrayList.subList(1,3);//左闭右开
        System.out.println(ret.toString());

    }

在这里插入图片描述
如果我们把ret的0下标修改,会不会影响arrayList的呢?

		ret.set(0,"xiaobai");
        System.out.println(ret.toString());
        System.out.println(arrayList.toString());

在这里插入图片描述
答案是会,修改ret的0下标相当于修改arrayList的1下标
也就是说,截取的是原来的地址,拿到的是原来的地址,所以修改也会影响原变量

4.ArrayList的遍历

1.直接输出

    public static void main(String[] args)
    {
        ArrayList<String> arrayList=new ArrayList<>();
        //ArrayList的父类的父类重写了toString方法
        arrayList.add("abc");
        arrayList.add("def");
        arrayList.add("wwww");
        arrayList.add("qaaaaaaa");
        arrayList.add("ddddddddddd");
        System.out.println(arrayList.toString());
        System.out.println("--------------------------------------");
        System.out.println(arrayList);

    }

在这里插入图片描述
2.根据下标遍历

		for (int i = 0; i < arrayList.size(); i++)
        {
            System.out.print(arrayList.get(i)+" ");
        }
        System.out.println();

3.foreach

//冒号的右边是你要传入的集合,冒号的左边是集合当中所定义的类型的变量
//拿到一个类型放到x里面然后打印
		for(String x:arrayList)
        {
            System.out.print(x+" ");
        }

4.迭代器
it指的是集合第一个元素的前一个位置

		Iterator<String> it=arrayList.listIterator();
        while(it.hasNext())//如果下一个有,走到下一个
        {
            System.out.print(it.next()+" ");//打印
        }
        System.out.println();

5.ArrayList的扩容机制

获取旧的空间大小,按照旧的空间的1.5倍来扩容的
如果用户所需扩容大小超过1.5倍,按照用户所需大小扩容

6.ArrayList相关题

1.CVTE面试题java--ArrayList_第7张图片

   public static void func(String str1,String str2)
    {
        List<Character> list=new ArrayList<>();
        for(int i=0;i<str1.length();i++)
        {
            char ch=str1.charAt(i);
            if(!str2.contains(ch+""))
            {
                list.add(ch);
            }
        }
        for(int i=0;i<list.size();i++)
        {
            System.out.print(list.get(i));
        }
        System.out.println();
    }
    public static void main(String[] args) {
        func("welcome to bit","come");
    }

2.扑克牌

创建两个类
在这里插入图片描述
card类代码

public class Card
{
    private String suit;//花色
    private int rank;//数字

    public Card(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;
    }
}

Test类代码

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test
{
    private static final String[] SUITS={"♥","♠","♣","♦"};
    public static List<Card> buyCard()//买牌
    {
        List<Card> cards=new ArrayList<>();
        for(int i=0;i<SUITS.length;i++)
        {
            for(int j=1;j<=13;j++)
            {
                Card card=new Card(SUITS[i],j);
                cards.add(card);
            }
        }
        return cards;
    }
    //如果我们要玩斗地主扎金花等游戏,牌的顺序这么齐肯定是不行的
    //所以我们要进行洗牌
    public static void shuffle(List<Card> cards)//洗牌
    {
        Random random=new Random();
        for(int i= cards.size()-1;i>0;i--)
        {
            int j= random.nextInt(i);
            Card tmp=cards.get(i);
            cards.set(i,cards.get(j));
            cards.set(j,tmp);

        }
    }
    public static void main(String[] args)
    {
        List<Card> cards=buyCard();
        System.out.println("牌到手了:");
        System.out.println(cards);
        System.out.println("---------------------------");
        System.out.println("洗牌:");
        shuffle(cards);
        System.out.println(cards);


        //有三个人,轮流揭牌五张
        List<Card> hand1=new ArrayList<>();
        List<Card> hand2=new ArrayList<>();
        List<Card> hand3=new ArrayList<>();

        List<List<Card>> hand=new ArrayList<>();
        //hand的每个元素都是List,而List的每个元素都是Card,相当于一个二维数组

        hand.add(hand1);
        hand.add(hand2);
        hand.add(hand3);

        //每个人拿一张牌
        for(int i=0;i<5;i++)
        {
            for(int j=0;j<3;j++)
            {
                Card card=cards.remove(0);//揭牌
                hand.get(j).add(card);//把card这张牌放到j这个人的手上
            }
        }
        System.out.println("第一个人的牌:");
        System.out.println(hand1);
        System.out.println("---------------------------");

        System.out.println("第二个人的牌:");
        System.out.println(hand2);
        System.out.println("---------------------------");

        System.out.println("第三个人的牌:");
        System.out.println(hand3);
        System.out.println("---------------------------");

        System.out.println("剩下的牌");
        System.out.println(cards);
    }
}

揭牌示例图
java--ArrayList_第8张图片
java--ArrayList_第9张图片

3.杨辉三角

杨辉三角leetcode链接
java--ArrayList_第10张图片

6. ArrayList的问题及思考

java--ArrayList_第11张图片
java--ArrayList_第12张图片

  1. ArrayList底层使用连续的空间,任意位置插入或删除元素时,需要将该位置后序元素整体往前或者往后搬
    移,故时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继
    续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
    思考: 如何解决以上问题呢?
    也就是我的下一篇博客–链表!

你可能感兴趣的:(java)