一、数组和集合的比较
数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺点,比数组更灵活更实用,而且不同的集合框架类可适用不同场合。如:
1.数组能存放基本数据类型和对象,而集合类存放的都是对象的引用,而非对象本身!
2.数组容易固定无法动态改变,集合类容量动态改变。
3.数组无法判断其中实际存有多少元素,length只告诉了数组的容量,而集合的size()可以确切知道元素的个数
4.集合有多种实现方式和不同适用场合,不像数组仅采用顺序表方式
5.集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性即可实现各种复杂操作,大大提高了软件的开发效率
二、List集合
有序列表,允许存放重复的元素;
实现类:
ArrayList:数组实现,查询快,增删慢,轻量级;(线程不安全)
LinkedList:双向链表实现,增删快,查询慢 (线程不安全)
Vector:数组实现,重量级 (线程安全、使用少)
三、ArrayList
底层是Object数组,所以ArrayList具有数组的查询速度快的优点以及增删速度慢的缺点。
而在LinkedList的底层是一种双向循环链表。在此链表上每一个数据节点都由三部分组成:前指针(指向前面的节点的位置),数据,后指针(指向后面的节点的位置)。最后一个节点的后指针指向第一个节点的前指针,形成一个循环。
双向循环链表的查询效率低但是增删效率高。
ArrayList数组线性表的特点为:类似数组的形式进行存储,因此它的随机访问速度极快。
ArrayList和LinkedList在用法上没有区别,但是在功能上还是有区别的。
四、LinkedList
LinkedList是采用双向循环链表实现的。
利用LinkedList实现栈(stack)、队列(queue)、双向队列(double-ended queue )。
它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()等。
经常用在增删操作较多而查询操作很少的情况下:
队列和堆栈。
队列:先进先出的数据结构。
栈:后进先出的数据结构。
注意:使用栈的时候一定不能提供方法让不是最后一个元素的元素获得出栈的机会。
五、集合的遍历--ArrayList
import java.util.*;
public class Test{
public static void main(String[] args) {
List list=new ArrayList();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用foreach遍历List
for (String str : list) { //也可以改写for(int i=0;i ite=list.iterator();
while(ite.hasNext())//判断下一个元素之后有值
{
System.out.println(ite.next());
}
}
}
三种方法都是用来遍历ArrayList集合,第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中会超出集合的长度。
六、ArrayList注意点(面试可能会被问到)
a.如果在初始化ArrayList的时候没有指定初始化长度的话,默认的长度为10.
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this(10);
}
b.ArrayList在增加新元素的时候如果超过了原始的容量的话,ArrayList扩容ensureCapacity的方案为“原始容量*3/2+1"哦。
/**
* Increases the capacity of this ArrayList instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
c.ArrayList是线程不安全的,在多线程的情况下不要使用。
如果一定在多线程使用List的,您可以使用Vector,因为Vector和ArrayList基本一致,区别在于Vector中的绝大部分方法都
使用了同步关键字修饰,这样在多线程的情况下不会出现并发错误哦,还有就是它们的扩容方案不同,ArrayList是通过原始
容量*3/2+1,而Vector是允许设置默认的增长长度,Vector的默认扩容方式为原来的2倍。
切记Vector是ArrayList的多线程的一个替代品。
d.ArrayList实现遍历的几种方法
package com.yonyou.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test{
public static void main(String[] args) {
List list=new ArrayList();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用foreach遍历List
for (String str : list) { //也可以改写for(int i=0;i ite=list.iterator();
while(ite.hasNext())
{
System.out.println(ite.next());
}
}
}
集合数组的相关方法
//collection接口方法
Collection t1 = new ArrayList();
//添加元素
t1.add("Jack");
t1.add("Merry");
System.out.println(t1);
//删除元素
t1.remove("Jack");
System.out.println(t1);
//获取元素个数
System.out.println(t1.size());
//判断是否包含一个元素
if (t1.contains("Merry")){
System.out.println("有Merry");
}else {
System.out.println("没有Merry");
}
//判断是否为空
if (t1.isEmpty()){
System.out.println("是空的");
}else {
System.out.println("不是空的");
}
//判断两个集合是否相同
Collection t2 = new ArrayList();
t2.add("Merry");
t2.add("Jack");
t2.add("tome");
t2.add("bluck");
if (t1.equals(t2)){
System.out.println("相同");
}else {
System.out.println("不相同");
}
//集合的情空
System.out.println("------------------");
//集合的遍历
/**1.使用Iterator遍历
* hasNext 判断是否有下一个对象
* next 获取下一个对象
* remove 删除当前遍历过后的对象
*/
Iterator iterator = t2.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//错误的方法
while (iterator.next() != null){
System.out.println(iterator.next());
}
System.out.println("------------------");
//2.用for-each 增强for循环
for (String obj: t2){
System.out.println(obj);
}
//List接口 extends Collection
// ArrayList 内部是连续的内存空间 优点:访问方便get(); 缺点:删除,添加比较难
// LinkedArrayList 内部使用链表实现 (不一定连续) 优点:增加 删除效率高 缺点:访问不方便
// 集合里面只能存放对象
// 包装类-->Byte Char Integer Long Float Double Boolean
// java会自动将基本数据类型包装为对应的类
ArrayList score = new ArrayList<>();
score.add(2);
score.add(3);
score.add(0,1);//在指定位置添加
System.out.println(score);
//访问元素
score.get(1);
System.out.println(score);
//修改元素 (下标,元素)
score.set(0,0);
System.out.println(score);
//删除元素 指定下标
score.remove(0);
System.out.println(score);
//删除指定的元素
score.remove((Integer)2);
System.out.println(score);
//清空
score.clear();
System.out.println(score);
ArrayList a2 = new ArrayList<>();
a2.add(1);
a2.add(2);
a2.add(3);
a2.add(4);
a2.add(5);
//加入元素 把另一个集合中的元素加入
score.addAll(a2);
System.out.println(score);
System.out.println("------------------");
ArrayList a3 = new ArrayList<>();
a3.add(1);
a3.add(2);
score.retainAll(a3);//取交集
System.out.println(score);
System.out.println("------------------");
ArrayList a4 = new ArrayList<>();
a4.add(1);
a4.add(2);
a4.add(3);
a4.add(4);
a4.add(5);
System.out.println(a4.indexOf(1));//第一次出现的位置
System.out.println(a4.lastIndexOf(1));//最后一次出现的位置
System.out.println("------------------");
//将ArrayList转化为普通数组
Integer[] object = new Integer[a4.size()];
a4.toArray(object);
System.out.println(object);
System.out.println("------------------");
Iterator iterator = a4.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("------------------");
//获取集合某个范围的子集合
List integerList = a4.subList(1,3);
System.out.println(integerList);
System.out.println("------------------");
ArrayList nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);
nums.add(4);
nums.add(5);
//Lambda表达式 删除对2取余结果为0的数
nums.removeIf( obj -> obj % 2 == 0);
System.out.println(nums);
// 1.使用方式:定义一个类来实现接口
ArrayClass ac = new ArrayClass();
int[] num = {1,2,3,4,5,6};
PXDClass pc = new PXDClass();
ac.test(num, pc);
// 2.使用匿名类
ArrayClass ac = new ArrayClass();
int[] num = {1,2,3,4,5,6};
ac.test(num, new Show() {
@Override
public void customShow(int element) {
System.out.println(element);
}
});
// 3.使用Lambda表达式
ArrayClass ac = new ArrayClass();
int[] num = {1,2,3,4,5,6};
ac.test(num, (int element) -> {System.out.println(element);});
}
}
// 闭包 把函数作为一个方法的参数
class ArrayClass{
public void test(int[] target, Show s){
for (int element: target){
s.customShow(element);
}
}
}
// 必须是接口 这个接口里面只有一个方法
interface Show{
void customShow(int element);
}
// 实现Show接口
class PXDClass implements Show{
@Override
public void customShow(int element) {
System.out.println(element);
}
}