一、ArrayList集合
前面说了数组,每个数组只能装一种类型的数据,那么有没有一种数组,能把所有东西都装下来呢?有没有一种数组,不用自己定义长度,能自由的伸缩呢?
有,这个就是ArrayList集合,一个能伸缩自如的动态数组
ArrayList数据结构:动态数组
二、集合的定义
ArrayList list = new ArrayList<>();
需要了解一下的是,集合实例化有有参构造的(查看API)了解即可
三、ArrayList增删改查(重点)
在集合中,最重要的是增删改查
3.1增 add
list.add(元素)
每次只能添加一个
前面说了,ArrayList是可以装下所有东西的,这是因为默认泛型为Object类型(一般情况下我们是需要添加泛型的)
public class Demo01 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
User user = new User();
int i = 5;
String str = "asd";
char c = 'a';
//增
list.add(user);
list.add(i);
list.add(str);
list.add(c);
System.out.println(list);
}
}
结果:
[demo.User@1540e19d, 5, asd, a]
3.2查 get
list.get(索引值)
ArrayList没有length(),取而代之的是size(),为集合长度
集合查询不像数组一样,list[1]这是错误用法
//延续上面代码
//查 get list.size()为集合长度
for (int j = 0; j < list.size(); j++) {
System.out.println(list.get(j));
}
这个for循环就是比较初始的迭代器,下面会说
3.3改 set
set(索引值,修改值)
在泛型为Object里(默认泛型为Object),它可以修改成任何值,但在指定泛型里就不可以了,只能修改成指定泛型
//延续上面代码
//改 set
list.set(0,6); //修改第一个值为6
list.set(1,6); //修改第二个值为6
list.set(2,6); //修改第三个值为6
//查看
for (int j = 0; j < list.size(); j++) {
System.out.println(list.get(j));
}
结果:
6
6
6
a
3.4删 remove
remove(index) 删除对应的索引值
remove(Object) 删除对应的元素
list.remove(1);
list.remove("asd");
四、ArrayList与泛型
在通常情况下,我们定义的集合都需要泛型来规范他们的类型
运用泛型,我们可以创建安全更好的集合,让问题尽可能在编译期就能抓到,而不会等到执行期才冒出来
4.1Object默认类型
下面说说Object为泛型的坏处(不定泛型就是默认为Object型)
这两者都是一样的
ArrayList<Object> list = new ArrayList<>();
ArrayList list = new ArrayList<>();
用Object接收,那么所有类型的值进入集合里后,都变成了Object类型,不能用回它原来的功能了
public class Demo04 {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<>();
list.add(new User());
list.add(500);
list.add("asdw");
Object o1 = list.get(0); //可以看到,里面的内容取出来,都是为Object类型
Object o2 = list.get(1);
Object o3 = list.get(3);
}
}
所有进去的元素,出来后都变成了Object,只是多态的结果
如果你想用回User的属性和方法,需要强转才行;
如果你想用回原来的int型500,需要强转才行;
如果你想用回String类型,需要强转才行… …
加上泛型后,就更加的规范安全了
泛型添加上去的是类,不能是8大基本数据类型,要用他的包装类
ArrayList list = new ArrayList<>(); 正确
ArrayList list = new ArrayList();错误
加入泛型后,所有的增加、修改都只能放入对应的类型,所有取值得到的对象都为泛型的类型
在后续我会单独拿出来,更深层地说明白集合和泛型的一些知识
五、迭代器
5.1fori迭代器
迭代器:迭代器是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址
就是我们能获取集合里的所有元素,这就是迭代器
就是普通的for循环(很多不称这为迭代器),但我认为这个既能索引所有的值,把每个值取出来并且能修改,是属于非常简单好理解的方法之一
public class Demo03 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
5.2 foreach
for(类型 赋予的值:迭代对象)
foreach是一个迭代器,是for循环的增强版,可以对迭代出来的元素进行操作,但不能修改
public class Demo03 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
for (int i:list) {
System.out.println(i);
}
}
}
理解为我们把list里面的元素一个一个的赋予给 i 了,所以我们对 i 进行修改不会影响list里面的元素变化
一般情况下我们只对他进行查看和一些其他的操作(如关流操作),而不对它修改。
5.3 迭代器 iterator
这个是集合专门用来生成以一个迭代对象的东西
- iterator:生产一个迭代器
- hasNext:查看下一个元素是否存在,如果下面还有元素则返回true,否则为false,要和next配套使用
- next:为下一个元素,让指针跳到下一个元素,一般情况下,next在一个循环里只能出现一次(如果出现两个或多个,那么指针会一直往下跳,越过一些元素)
next返回的值为当前指针对应的值,获取值后跳再跳到下面
例如:Integer next = it.next();
public class Demo03 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
//生成迭代器
Iterator<Integer> it = list.iterator();
//迭代过程
System.out.println(it.hasNext());
it.next();
System.out.println(it.hasNext());
it.next();
System.out.println(it.hasNext());
it.next();
System.out.println(it.hasNext());
it.next();
System.out.println(it.hasNext());
}
}
结果:
true
true
true
false
Exception in thread "main" java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:854)
at demo.Demo03.main(Demo03.java:21)
可以看到,当有值时候,hasNext返回true,下一值没有了返回false
而next到下一个值,如果没有,就会报错(NoSuchElementException列表为空)
正确用法
public class Demo03 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
Integer next = it.next();
System.out.println(next);
}
}
}