1. Java本身提供的ArrayList
在ArrayList和顺序表(上)那一节里面,我们自己实现了ArrayList的底层大部分代码,在这个基础上,我们就可以开始来了解Java本身提供的ArrayList.
1.1 ArrayList的三种构造方法
方法 | 解释 |
ArrayList() | 无参构造 |
ArrayList(Collection<? extends E > c) | 利用其他的Collection构造ArrayList |
ArratList(int innitialCapacity) | 指定顺序表初始容量 |
我们先来介绍第一和第三个
第一个构造方法,如果我们不设置任何参数,这里会直接给我们一个空的Object数组,里面没有大小.
第二个构造方法,我们指定的容量是合法的,我们就产生一个指定容量大小的数组,
第三个构造方法,我们必须要理解 Collection<? extends E > c 这个是什么意思
我们来举个例子
所以我们就晓得第二个构造方法的主要用法了:
1. 该集合类必须实现Collection接口
2. 在第一个<>设置的类型必须是第二个<>的子类或者它自己
这样就能实现直接把另一个实例的内容作为我新的实例的内容.
我们来看代码:
public static void main(String[] args) {
//ArrayList第二个构造方法 ,要求必须实现Collection,并且放进去的东西是子类(这个搞清楚是谁的子类)
ArrayList<Integer> list = new ArrayList<>();//TODO 虽然没有分配内存
list.add(1);//TODO 结论1.但是第一次Add的时候会分配大小为10的内存
list.add(2);//TODO 结论2.如果超过了,就会1.5倍自动扩容
list.add(3);//添加元素
list.add(0,99);
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i)+" ");
}
System.out.println();
//相当于直接把一组数据放进来了
ArrayList<Number> list2 = new ArrayList<>(list);//Integer是Number的子类,因此可以放进来
LinkedList<Integer> list1 = new LinkedList<>();
list1.add(1);
list1.add(2);
list1.add(4);
ArrayList<Number> list3 = new ArrayList<>(list1);//Integer是Number的子类,因此可以放进来
list3.add(1123);
list3.add(1124);
System.out.println(list3);
System.out.println(list1);
}
我们主要要主要这个
我们可以来看看源码(了解即可)
结论:
1. 我们在创建ArrayList实例的时候,不设置参数,我们调用的是无参构造方法,里面是一个空的数组,没有分配内存.
2. 当第一次add的时候,我们才会分配大小为10的内存
3. 如果add方法检测出size大小等于数组大小,就会进行1.5倍的扩容
1.2 ArrayList方法的介绍
方法 | 解释 |
boolean add(E e) | 在最后一个有效数据后面插入e |
void add(int index,E e) | 把插入到index位置 |
void 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 e) | 把下标index位置元素设置为e |
E clear() | 清空 |
boolean contains(Object o) | 判断o是否在线性表里面 |
int indexOf(Object o) | 返回第一个o所在的下标 |
int lastIndexOf(Object o) | 返回最后一个o的下标 |
List<E> subList(int fromIndex,int toIndex) | 截取部分list |
我们来使用一下这些方法
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
ArrayList<Number> list1 = new ArrayList<>();
list.add(1);//TODO add的使用
list.add(2);
list.add(3);
list.add(10);
list.add(9);
list.add(90);
list.add(90);
list.add(2,54);
list1.addAll(list);
//我们是可以直接通过list打印,因为它实现的一个接口重写了toString方法
System.out.println("list:"+list);
System.out.println("list1:"+list1);
System.out.println("=============");
list.remove(1);//TODO remove的使用
list.remove(new Integer(3));
System.out.println("list:"+list);
System.out.println("==========");
System.out.println(list.get(2));//TODO get的使用
list.set(3,190);//TODO get的使用
System.out.println("list:"+list);
System.out.println("==========");
System.out.println(list.contains(1));//TODO contains的使用
System.out.println(list.indexOf(90));//TODO indexOf的使用
System.out.println(list.lastIndexOf(90));//TODO lastIndexOf的使用
System.out.println(list);
list.clear();
System.out.println(list);
}
list:[1, 2, 54, 3, 10, 9, 90, 90]
list1:[1, 2, 54, 3, 10, 9, 90, 90]
=============
list:[1, 54, 10, 9, 90, 90]
==========
10
list:[1, 54, 10, 190, 90, 90]
==========
true
4
5
[1, 54, 10, 190, 90, 90]
[]
我们需要注意的几个地方
addAll()里面我们放的是一个Number类型或者其子类的对象
remove里面,如果我们是想移除一个数,而不是移除下标的数,我们里面的参数就是引用类型的对象
list.remove(new Integer(3));
还有一个方法
List<E> subList(int fromIndex,int toIndex)
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
List<Integer> list1 = list.subList(0,2);
System.out.println("list1" + list1);
System.out.println("list" + list);
System.out.println("====");
list1.add(123);
list1.set(0,99);
System.out.println("list1" + list1);
System.out.println("list" + list);
}
list1[1, 2]
list[1, 2, 3, 4]
====
list1[99, 2, 123]
list[99, 2, 123, 3, 4]
我们可以得到一下几个结论:
1. subList的参数设置是[第一个参数,第二个参数)
2. subList的返回值是一个List类型的
3. 我们subList方法并不会产生一个新的对象,而是直接把list的地址传给了list2,因此我们操作list2的时候list也会发生改变
1.3 ArrayList的遍历
ArrayList可以通过四种方式来进行遍历,直接打印对象名字,for循环,foreach,使用迭代器
1> 我们直接通过打印对象名
2> 我们通过for循环来打印
3> 我们通过foreach来打印
4> 我们通过迭代器进行打印
使用迭代器来遍历集合类,我们只需要实现Iterable接口即可
由下图可知,ArrayList是实现了Iterable接口的
因为迭代器写法我们比较陌生,我们再来看看它的形式
Iterator<引用数据类型> 对象名 = 实现了Iteratable接口的对象.Iterator();
whie(对象名.hasNext()) {
System.out.print(it.next()+" ");}
2. 练习题
2.1 杨辉三角
题目:
我们在写这个题目之前先了解一下List的二维数组的写法
解题步骤
1. 我们先处理第一行的数据,第一行就是1,我们直接把一维数组的第一行数据设置为1,然后把第一行放到二维数组里面
2. 从第2行开始我们开始计算每个list中的数据
我们先准备当前行的数据,就需要一个List类型的一维数组,然后我们放入每一行的第一个元素,就是1,然后我们构造每一行中间的数据,我们需要获得上一行的数据,我们通过ret.get(i-1)获得上一行,然后构造下一行的中间数据,通过preRow.get(j-1),preRow.get(j)来获得上一行元素的前一个,和上一行的正上方一个,然后把他们相加就是本行数据的值,然后我们把它加入到当前行里面去.
3. 把1加入到当前行的最后一个位置
4. 把当前行加入到ret二维数组里面去
整体代码
class YangHuiTriangle {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> list = new ArrayList<>();
//TODO 1.先处理第一行的数据
list.add(1);//每一行代表一个list,第一行放的元素是1
ret.add(list);//把第一行放入二维数组
//TODO 2.从第2行开始计算每个list中的数据
for (int i = 1 ; i < numRows ;i++) {
//TODO 3.先准备当前行数据
List<Integer> curRow = new ArrayList<>();
//TODO 4.当前行的第一个数据
curRow.add(1);
//TODO 5.准备当前行的中间元素:上一行的前一个,上一行的正上方一个
//找到前一行
List<Integer> preRow = ret.get(i - 1);
//构造下一行
for (int j = 1 ; j < i ; j++) {
//通过get方法来获取顺序表里面的值
int val = preRow.get(j)+preRow.get(j-1);
//然后放进当前行里面
curRow.add(val);
}
//TODO 6.准备当前行的最后一个数据
curRow.add(1);
//TODO 7.当前行放进ret二维数组里面
ret.add(curRow);
}
return ret;
}
}
2.2 简单的洗牌算法
主要的步骤
1. 生成一副扑克牌
2. 洗牌
3. 发牌
我们规定3个人来抓牌,每个人轮流抓5张(一共抓了15张牌
我们先构造出Card这个类,一个牌时由花色和数字组成的,我们在这个类里面设置这俩个属性,
并且提供相应的构造方法.又因为是private 修饰的,我们需要为这俩个属性设置set和get方法,并且我们重写了toString方法.
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;
}
//打印牌,需要toString方法
@Override
public String toString() {
return suit+": " + rank+" ";
}
}
然后我们写一个cardDemo类来对Card进行构造
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CardDemo {
//四种花色
private final String[] suits = {"♥","♠","♦","♣"};
//买牌
public List<Card> buyCard() {
List<Card> cardList = new ArrayList<>();
//TODO 1.生成牌
for (int i = 0; i < 4; i++) {//花色
for (int j = 1; j <= 13; j++) {//数字
Card card = new Card(suits[i],j);//每一张花色产生13个数字
cardList.add(card);//把创建出来的每一张牌都放进去
}
}
return cardList;
}
//TODO 2.洗牌
public List<Card> shuffle(List<Card> cardList) {
Random random = new Random();
//我们从最后面开始,第50张和前面49张进行随机交,然后第49张和前面48张进行交换
for (int i = cardList.size() - 1; i > 0 ; i--) {
int index = random.nextInt(i);
// 我们把 index 和 i 进行交换
swap(cardList,i,index);
}
return cardList;
}
private void swap(List<Card> cardList,int a,int b) {
Card stm = cardList.get(a);
cardList.set(a,cardList.get(b));
cardList.set(b,stm);
}
//TODO 3.发牌,三个人,每人轮流揭牌5张
public void getCard(List<Card> cardList) {
//每个人相当于一个一维的Card数组
List<Card> hand1 = new ArrayList<>();
List<Card> hand2 = new ArrayList<>();
List<Card> hand3 = new ArrayList<>();
List<List<Card>> hands = new ArrayList<>();
hands.add(hand1);
hands.add(hand2);
hands.add(hand3);
//3个人轮流抓五张
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 3; j++) {
Card card = cardList.remove(0);//去除每一张摸走的牌
hands.get(j).add(card);//发给每个人
}
System.out.println("第一个人的牌: ");
System.out.println(hand1);
System.out.println("第二个人的牌: ");
System.out.println(hand2);
System.out.println("第三个人的牌: ");
System.out.println(hand3);
System.out.println("剩下的牌: ");
System.out.println(cardList);
}
}
}
我们分段进行解析这个代码:
1. 生成牌
我们需要四种花色
每个花色有13张牌因此俩层循环嵌套,然后用Card来创建每一张牌,并且把每一张card放进cardList里面去
2. 洗牌
我们从最后面开始,假设是第50张牌,我们就让它和前面49张牌随机一张进行交换
3. 发牌
我们每一个人相当于一个Card数组,因此List<Card> hand1 = new ArratList<>();然后我们再生成一个二维数组hands,然后3个人轮流抓五张牌,每次抓一张牌就要把cardList的牌数减少一张(0),表示我们从最上面开始抓
标签:顺序,ArrayList,list,System,add,println,out From: https://blog.csdn.net/2201_75880772/article/details/142914521