Collection体系集合之List
1. Collection父接口
特点:代表一组类型的对象,是无序、无下标的。
简单的方法介绍:
- boolean add()//添加一个元素
- boolean addAll()//将指定集合的元素全部添加到目标集合
- void clear()//移除所有的元素
- boolean contains()//判断是否包含
- boolean equals(Object o)//判断是否相等
- Iterator iterator()//迭代器
- boolean remove()//移除元素
- boolean retain()//保留某某某元素
- int size()
- toArray() //数组相关
集合一般都是围绕增删查改,遍历展开的。
集合遍历方法及介绍
//遍历1.利用for进行遍历
for (Object object : collection){
String str = (String)object;
System.out.println(str);
//collection.remove(object); 会出现并发修改异常,利用for不能删除元素
}
//遍历2.使用迭代器
//迭代器利用三个统一的方法进行遍历所有集合hasNext()、next()、remove()
Iterator it = collection.iterator();
while (it.hasNext()){//是否有下一个元素
Object o = it.next();//返回元素
System.out.println(o);
//it.remove(); //删除元素
}
//注意事项:使用迭代器或者是for进行遍历的时候,不能使用集合的删除方法进行元素删除。
//只能使用迭代器进行删除,否则会出现并发修改异常(ConcurrentModificationException)
2. 接口List
2.1 List总述
特点:有序,有下表,元素的值是可以重复的
方法介绍:(介绍List有但是Collection没有的)
- E get()//返回指定位置元素
- int indexOf(Object o)//返回第一次出现某元素的索引,没有就返回-1
- listIterator//功能比Iterator更加强大
- void set(int index, E element) //修改
- List subList(int from, int to)//截取列表
List遍历方式如下
//List遍历
//1.使用for,还是不能利用集合本身的方法进行删除,不能添加,可以修改
//2.使用Iterator
//3.使用ListIterator(可以删除、添加、逆向遍历、修改)
ListIterator lit = list.listIterator();
while (lit.hasNext()){
System.out.println(lit.nextIndex()+" "+lit.next());
}
//逆向
while (lit.hasPrevious()){
System.out.println(lit.previousIndex()+" "+lit.previous());
}
//4.利用下角标
for (int i = 0;i < list.size(); i++){
System.out.println(list.get(i));
}
List删除方法介绍
List<Student> list = new ArrayList<Student>();
Student stu1 = new Student(1,"11",12);
Student stu2 = new Student(2,"22",13);
Student stu3 = new Student(3,"33",14);
list.add(stu1);
list.add(stu2);
list.add(stu3);
System.out.println(list.toString());
//删除元素 方法1
list.remove(stu1); //可以删除元素
System.out.println(list.toString());
//删除元素 方法2
list.remove(new Student(2,"22",13));
System.out.println(list.toString());
//发现运行之后并没有删除
上述代码运行结果如图所示
可以看到第二种方式并没有删除成功,这是由于默认的equals函数比较的是两个对象的地址,新建的(2,22,13)的地址与原本的地址肯定不同所以是删除不掉的。
这个时候,如果想利用这种方式进行删除,只需要重写equals方法,使其比较的是“值”,也就是说我要删除的是和(2,22,13)这个对象值相同的元素。
在Student里面重写equals
@Override
public boolean equals(Object o) {
if (o == null)
return false;
if(this == o)
return true;
if(o instanceof Student){
Student stu = (Student)o;
if(this.ID == stu.ID && this.name.equals(stu.name) && this.age == stu.age){
return true;
}
}
return false;
}
如此,运行结果如下
可以发现成功删除了
注:同样的理论可以,还可以用在contains里面这种。。。就不进行赘述了。
2.2 ArrayList
内部使用数组实现,查询元素较为高效,删除和增加元素较慢。
ArrayList的add函数源码介绍
- ArrayList的无参构造函数会实现创建一个长度为0的数组。
- 在添加第一个元素的时候,这个数组的长度会更新为10,并将第一个要添加的元素的放在第0位置。
- 之后当添加的元素数量超出当前数组的容量时,数组的长度会变为其原本长度的1.5倍。
remove介绍(此处的remove是利用下标进行元素移除的remove)
主要有两步
- 计算要移动的元素个数
- 利用了System.arraycopy()这个函数
上述的源码如下所示:
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
其中 elementData是存储元素的数组,index为当前移除元素的下标。
2.3 LinkedList
特点:删除和增加的效率要高,查询的效率低
与ArrayList的不同之处在于,ArrayList是使用数组,而LinkedList使用的是双向链表结构。
具体的使用方法与ArrayList一样,就不再进行赘述了。
2.4 Vector
Vector的方法中多了一个枚举方法,因此其遍历方法一共有五种:
- 增强for
- Iterator
- ListIterator
- for
- 枚举
枚举方法的代码如下所示:
Enumeration en = vector.elements();
while (en.hasMoreElements()){
en.nextElement();
}
Vector与ArrayList的实现方法比较
Vector | ArrayList |
数组实现 | 数组实现 |
线程安全 | 线程不安全 |
效率较低 | 效率较高 |
2.5栈与队列
- 栈:Stack类继承自Vector接口,主要两种方法push(入栈)、pop(出栈)。
- 队列:Queue接口,继承自Collection接口,主要方法两种offer(入队)、poll(出队)。
上述两种接口,LinkedList也都有所实现,二者的简单使用代码如下所示。
//Stack stack = new Stack();
LinkedList stack = new LinkedList();
stack.push("wo");
stack.push("ni");
stack.push("ta");
int count = stack.size();
for(int i = 0;i < count; i++){
Object o = stack.pop();
System.out.println(o);
}
Queue queue = new LinkedList();
queue.offer("wo");
queue.offer("ni");
queue.offer("ta");
int count1 = queue.size();
for(int i = 0; i < count;i++){
System.out.println(queue.poll());
}
System.out.println(queue.size());
注:此处的pop、poll都是直接出栈、出队。
3. 集合与泛型
3.1 简单的例子
泛型,集合都是使用泛型的,例子:
ArrayList<Pig> pigs = new ArrayList<Pig>();
Pig pig1 = new Pig(1,"xiaomi");
Pig pig2 = new Pig(2,"dami");
pigs.add(pig1);
pigs.add(pig2);
Iterator<Pig> it = pigs.iterator();
while (it.hasNext()){
System.out.println(it.next().toString());
}
都加上类型,更加规范。不加类型的时候,默认是Object
3.2 集合与泛型与“?”
public static void main(String[] args) {
ArrayList<Pig> pigs = new ArrayList<Pig>();
Pig pig1 = new Pig(1,"xiaomi");
Pig pig2 = new Pig(2,"dami");
pigs.add(pig1);
pigs.add(pig2);
ArrayList<String> list = new ArrayList<String>();
list.add("ni");
list.add("wo");
list.add("ta");
}
上述pigs和list是否可以通过一个函数进行遍历。如何实现?
方法如下:
public static void main(String[] args) {
ArrayList<Pig> pigs = new ArrayList<Pig>();
Pig pig1 = new Pig(1,"xiaomi");
Pig pig2 = new Pig(2,"dami");
pigs.add(pig1);
pigs.add(pig2);
ArrayList<String> list = new ArrayList<String>();
list.add("ni");
list.add("wo");
list.add("ta");
show(pigs);
show(list);
}
public static void show(ArrayList<?> list){
Iterator<?> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
注:此处的“?”表示任何类型。
运行结果如下:
此处的"?"在使用的时候,还可以规定其上限以及下限。
- 泛型的上限,? extend Pig ,"?"只能是pig以及Pig的子类
- 泛型的下限,? super Pig ,"?"只能是Pig以及Pig的父类
具体的使用代码如下:
public static void show1(ArrayList<? extends Pig> list){
Iterator<?> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
主函数里的调用代码如下:
ArrayList<PetPig> petpigs = new ArrayList<PetPig>();
petpigs.add(new PetPig(12,"dahuang"));
show1(petpigs);
4. 集合的工具类Collections
常用的方法,直接上例子吧。
比较简单
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(102);
list.add(100);
list.add(10);
list.add(55);
//排序
System.out.println("排序之前"+list.toString());
Collections.sort(list);
System.out.println("排序之后"+list.toString());
//二分查找
int pos = Collections.binarySearch(list,100);
System.out.println(pos);
System.out.println(list.get(pos));
//注意目标集合的大小要和原集合的大小要大于等于
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for(int i = 0;i < list.size();i++ )arrayList.add(0);
Collections.copy(arrayList,list);
//反转
Collections.reverse(list);
System.out.println("反转之后的list"+ list.toString());
//打乱顺序
Collections.shuffle(list);
System.out.println(list.toString());
}
5. 集合与数组
集合与数组可以相互转换的。
- 数组转集合
//数组转集合
//转完之后不能添加和删除元素,但是可以使用集合的方法
String[] persons = {"ni","wo","ta"};
List<String> list1 = Arrays.asList(persons);
- 集合转数组
//集合转数组
//new String[0],是为了获取类型
//如果new的数组的长度(String[0])小于或等于集合的长度,返回的数组的长度和集合一样(此时arr的长度为3)
//如果new的数组的长度大于集合(String[10])的长度,则返回数组的长度的和指定的长度一致(此时arr的长度为10)
String[] arr = list1.toArray(new String[0]);
System.out.println(arr.length);
里面的注意事项,可以在自己的机器上跑一跑,就会很明确。