java学习day4--集合
Collection
是单列集合的祖宗接口,所有单列集合都可继承。有如下方法:add(),clear(),remove(),contain(),isEmpty(),size().
collection是一个接口,因此不能直接创建他的对象,需要创建实现其实现类的对象。
Collection中方法
往list集合中添加数据,add()方法永远返回true(因为数据可以重复)。而对于set集合,添加原先不存在的数据会提示true,而对于原先已存在的数据会提示false(set集合不可重复)。
对于remove()方法,只能通过对象删除,不能通过索引删除。删除成功提示true,失败为false;
对于contains()方法,判断是否包含,返回的是布尔值。当集合中存储的是自定义对象时(即Collection<(此处为自定义对象时)> coll = new ArrayList();),若也想通过contains方法来判断元素是否存在,则需在对应的自定义对象的javabean中重写equals()方法(为什么:因为contains()方法底层调用了equals()方法进行判断,若在自定义对象中不重写,则会自动调用父类Object的equals()方法,而Object中进行比较是利用地址值进行比较的,因此会出现错误)
对于inEmpty()方法,判断集合长度是否为空
size()方法,获得集合长度
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
System.out.println(coll);
// coll.clear();
// System.out.println(coll)
coll.remove("aaa");
System.out.println(coll);
boolean a = coll.contains("aaa");
System.out.println(a);
}
}
Collection中遍历
1.迭代器遍历
迭代器(Iterator)遍历不依赖索引。
迭代器通过判断下一个有无元素,并且不断移动指针实现遍历。
正因为迭代器中有romove()的删除方法,因此当遍历过程中需要删除元素时可使用,若仅需要遍历则可使用增强for或lambda表达式。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo2 {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//用集合对象获取迭代器对象
//此时迭代器默认指向0索引
Iterator<String> iterator = coll.iterator();
while(iterator.hasNext()){
String str = iterator.next();
System.out.println(str);
}
}
}
注意:1.迭代器遍历完毕,指针不会复位(不会自动回到开头)。2.想再次遍历,只能再获取一个迭代器对象。3.循环中只能一次next,迭代器遍历不能用集合方式进行增删(迭代器有自带的删除方法remove(),)。4.当迭代器指针指向最后没有元素位置时,会报NosuchElementException异常,而非数组越界类似的异常。
2.增强for遍历
底层就是迭代器,简化了迭代器的书写。
单列集合和数组才可以用增强for进行遍历。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo2 {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//迭代器遍历
//用集合对象获取迭代器对象
//此时迭代器默认指向0索引
// Iterator<String> iterator = coll.iterator();
//
// while(iterator.hasNext()){
//
// String str = iterator.next();
// System.out.println(str);
//
// }
//增强for遍历
//c是第三方变量,依次表示集合中各个元素
//coll.for
//以上输入方式可以快速生成增强for循环
for (String c : coll){
System.out.println(c);
}
//
}
}
3.lambda表达式遍历
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
public class CollectionDemo2 {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//迭代器遍历
//用集合对象获取迭代器对象
//此时迭代器默认指向0索引
// Iterator<String> iterator = coll.iterator();
//
// while(iterator.hasNext()){
//
// String str = iterator.next();
// System.out.println(str);
//
// }
//增强for遍历
//c是第三方变量,依次表示集合中各个元素
//coll.for
//以上输入方式可以快速生成增强for循环
// for (String c : coll){
// System.out.println(c);
// }
//匿名内部类-->lambda表达式
//forEach方法底层是使用for循环遍历集合,把得到的元素传递给accept方法中的s。
coll.forEach(new Consumer<String>() {
@Override
//s依次表示集合中每个数据
public void accept(String s) {
System.out.println(s);
}
});
//lambda表示式
coll.forEach(s-> System.out.println());
}
}
List
collection的方法list都继承了,list因为有索引有额外的关于索引的操作。
List方法
add(),remove(),set(),get()。(这些方法都是可以根据索引直接操作的方法)
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
System.out.println(list);
//add方法,添加元素,后面元素依次后移
list.add(1,"nnn");
System.out.println(list);
//remove删除指定索引元素,后面元素依次前移
//方法出现重载,会默认调用实参和形参类型相同的方法。
//当集合中数据为数字时,想直接根据数值删除,需要进行手动装箱操作
//Integer i = Integer.valueOf(1);
list.remove(2);
System.out.println(list);
//set
list.set(1,"666");
System.out.println(list);
}
}
List集合的遍历方式
1.迭代器
与collection类似
2.列表迭代器(特殊)
这是list集合特殊的迭代器,也就因为是list集合,所以其存在索引,因此,它存在在迭代器过程中进行增加的功能,这也就是与普通迭代器不同的地方。listIterator也有特殊的循环方法存在从前往后,与从后往前两种(但是从后往前具有一定局限性,需要先让迭代器的指针走到最后,再从后往前走)
3.增强for
与collection类似
4.lambda表达式遍历
与collection类似
5.普通for(根据索引)
与collection类似
总代码:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
public class ListDemo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
Iterator<String> iterator = list.iterator();
//迭代器
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
System.out.println("--------------");
//增强for
for (String s : list) {
System.out.println(s);
}
System.out.println("--------------");
//lambda表达式
list.forEach(s->System.out.println(s));
System.out.println("--------------");
//普通for
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
System.out.println("--------------");
//列表迭代器
//列表迭代器可以在迭代器的遍历过程中进行增加删除(这是与普通迭代器不同的地方)
//这一部分与原来的迭代器是一摸一样的。
ListIterator<String> it = list.listIterator();
while (it.hasNext()){
String next = it.next();
if("bbb".equals(next)) {
it.add("这是用list迭代器的方法进行数据添加");
}
}
System.out.println(list);
}
}
总结:在遍历过程中需要删除元素,使用迭代器。
在遍历过程中需要增加元素,使用列表迭代器。
仅仅想要实现遍历,使用增强for或lambda表达式。
如果遍历过程中想要对索引进行操作,可用普通for循环。
ArrayList
他的父类有Collection和List。继承了他们的方法。
ArrayList的底层原理
ArrayList的底层是数组结构的。
利用空参构造创建ArrayList集合(叫做ElementData),会在底层创建一个默认长度为0的数组。
添加第一个元素会创建一个新的长度为10(此处10,是java中默认的数组初始值,DEFAULT_CAPACITY)的数组。用size指向0索引。(size即表示元素个数,又表示下一个元素应该存入的位置)
当元素存满时数组扩容有两种情况1.数组会扩容1.5倍,也就是新建一个大1.5倍的数组,将原数组拷贝进去。2.当一次添加的数组极大,远远超过扩容1.5倍的大小,因此此时创建的新数组长度就以实际长度为准。
LinkList
LinkList的底层原理
LinkList的底层是双向链表,查询慢,增删快。LinkList也有很多独有的API,用于头尾元素的处理:
addFirst(),addLast(),getFirst(),getLast(),removeFirst(),removeLast()。(这些方法的效果用其父类list的方法也可以解决,因此这些方法使用不多。)
一个Node由三个成员变量组成(item,next,prev),存储当前数据,下一个数据节点,上一个数据节点。
主要是使用LinkLast方法实现链表的形成。
Interator的底层原理
调用iterator方法实际上就是创建了一个迭代器对象,会初始化三个成员变量。创建一个指针cursor(默认指针指向0索引)。LastRet = -1 会指向刚刚指向的索引。modCount指代集合变化的次数,用来记录迭代器中对数据进行操作的次数,如果在这用集合的方式修改了数据,就会像上面提到的迭代器不能用集合方法进行数值修改,报出并发修改异常。
hasNext(),方法中使用cursor != size 进行判断,输出布尔值。(就是用光标的索引和数组的长度进行比较。)
next()方法最终return了一个elementData,也就是返回了索引所指的元素值,并将索引后移一位。
问:如何避免并发修改异常
答:避免在使用迭代器或增强for遍历数组过程中使用集合的方法增加或删除元素,深层原因如上modCount。
更多推荐




所有评论(0)