集合和数组的区别 List与其实现类ArrayList,LinkedList方法与内存分析
要了解集合和数组的区别,ArrayList和LinkedList内存的储存方式和熟练运用常用方法
集合
Java 的一种的容器,可以多多个数据进行存储
数组的长度是固定的,每添加一个新元素,就要创建一个新数组,长度为原数组+1,再把原数组的内容复制到新数组中,再添加新元素
集合实质就是把对数组的操作封装为了方法;添加元素时,底层就是对数组的拷贝:长度+1,调用者感知不到,只告诉自己添加了元素,用户操作的时候就觉得是一个可以伸缩的容器
集合和数组的区别
相同:
-
都是用来存储数据的容器
-
变量繁多散乱不易于统一管理
-
使用容器的元素,就是希望能用有规律的方式去操作大量的数据,往往都是通过索引操作存储的数据
不同点:
-
数组可以存储基本类型和引用类型的数据
-
集合只能存储引用数据类型的数据,如果是基本数据类型,jdk1.5之后,会自动装箱,再进行储蓄
容器的可不可变
-
数组长度是固定不可变
-
集合长度是可变的,可伸缩
操作数据的方式
-
数组中仅有object继承过来的方法,操作元素只能通过数组名下标方式进行操作
-
集合中有很多方法都能用来操作元素
集合分为:
单列集合:每个元素就是一个单独的个体
双列集合:每个元素都是一对数据,把这一对数据当做一个整体去操作
Collection
单列集合的顶层根接口
定义的是所有单列集合共有的方法
Collection是一个接口,不能直接创建对象,r若要用他的方法只能让他指向实现类对象,这样就可以调用Collection中定义的公共方法为
Collection c = new ArrayList(); 通过多态的方式,完成Collection下方法的使用
Collection的常用方法
-
add(Object c): 将c元素添加到集合中
-
remove(Objcet c): 将c元素从集合中删除
-
clear(): 清空集合中的内容
-
size(): 获取集合中元素的个数
-
isEmpty():判断是否为空,当且仅当长度为0的时候返回true
-
contains(Object c) 判断集合中是否包含元素c
-
addAll(Collection c):将c中所有的元素,添加到调用者集合中
-
containsAll(Collection c):判断调用者集合是否包含元素c中的所有元素
-
removeAll(Collection c):删除调用者集合中所有c中元素
-
retainAll(Collection c):参数c中有哪些元素,就在调用者集合中,保留哪些元素
package Test2;
import java.util.ArrayList;
import java.util.Collection;
public class Tt {
public static void main(String[] args) {
Collection c = new ArrayList();//使用多态方式去创建对象
c.add("2");
c.add("6");
c.add(1);;//只能添加引用数据类型,如是基本数据类型,jdk1.5之后会自动装箱
System.out.println(c.size());//获取元素个数
System.out.println(c.contains("6"));//判断是否包含某个元素
c.remove("2");//删除某个元素
System.out.println(c);
c.clear();
System.out.println(c);
System.out.println(c.isEmpty());//判断是否为空
System.out.println("=========================");
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
Collection c2 = new ArrayList();
c2.addAll(c1);//将c1中的元素,全部添加到c2中
System.out.println(c2);
System.out.println("=========================");
Collection c3 = new ArrayList();
c3.add("a");
c3.add("b");
c3.add("c");
c3.add("d");
//判断是否包含全部元素
System.out.println(c3.containsAll(c1));
System.out.println("=========================");
c3.retainAll(c1);//保留c3和c中的交集,相同的元素
System.out.println(c3);
c3.removeAll(c1);//删除所有元素
System.out.println(c3);
}
}
遍历方式
用toArray()方法将集合中的元素,存储到Object数组中完成遍历
package Test2;
import java.util.ArrayList;
import java.util.Collection;
public class Tt {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add("1");
col.add("2");
col.add("3");
col.add("4");
System.out.println(col);
Object[] arr = col.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
迭代器
一个接口java.util.Iterator,用来遍历集合中所有的元素,将集合中的元素一个一个遍历出现的对象
获取迭代器的方式:集合中专门提供了一个方法获取迭代器对象
Iterator iterator()
迭代器有三个方法
-
hasNext() 判断迭代器当前指向位置是否有元素
-
next() 取出迭代器指向位置的元素将集合中的元素,一个一个遍历出现的对象
-
remove() 删除迭代器指向位置的元素
package Test2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Tt {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add("1");
col.add("2");
col.add("3");
col.add("4");
Iterator iterator = col.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
System.out.println(o);
}
}
}
注意:Exceptioninthread"main"java.util.NoSuchElementException
一旦当迭代器到最后的位置的时候,继续调用就会抛出异常
-
使用的时候,一定要通过hasNext方法判断当前位置是否有元素
-
不要只判断一次,调用多次next方法
List
列表类型
特点:有序,每个元素有有自己的位置,通过不同的位置来区分元素
list接口下实现类存储的元素,可以重复
List特有的方法
-
add(int index,Object obj):向指定位置index插入一个元素obj
-
remove(int index):根据位置删除一个元素
-
set(int index,Object):将指定位置index的元素,替换为obj
-
get(int index):获取指定位置index的元素
package Test2; import java.util.ArrayList; import java.util.List; public class Tt { public static void main(String[] args) { List l = new ArrayList(); l.add(0,"aa"); l.add(0,"bb"); l.add(2,"cc"); l.add(3,"dd"); System.out.println(l); l.set(0, "ww");//修改指定位置的元素 System.out.println(l); Object o = l.get(0);//获取一个元素 System.out.println(o); Object o2 = l.get(2); System.out.println(o2); l.remove(1);//删除一个元素 System.out.println(l); } }
遍历的方式
使用size() 获取元素个数,通过get()取出对应位置的元素
package Test;
import java.util.List;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
List l =new ArrayList();
l.add(0,"a");
l.add(0,"b");
l.add(2,"c");
l.add(3,"d");
System.out.println(l);
for (int i = 0; i < l.size(); i++) {
if (l.get(i).equals("b")) {
l.add("ee");
}
}
System.out.println(l);
}
}
并发修改异常
发于在使用迭代器遍历集合时,修改了集合的长度(使用集合对象修改了长度)
java.util.ConcurrentModificationException
解决方式
使用增强型迭代器进行对集合的遍历
-
使用listIterator() 获取ListIterator对象,在迭代的过程中使用迭代器来完成对集合元素的增删
-
常用方法add() 迭代过程中添加一个元素, remove迭代过程中删除当前指向的一个元素
解决方式2
- 不使用迭代器遍历,使用普通for循环对集合进行遍历
package Test2;
import java.util.List;
import java.util.ListIterator;
import java.util.ArrayList;
import java.util.Iterator;
public class Tt {
public static void main(String[] args) {
List l =new ArrayList();
l.add(0,"a");
l.add(0,"b");
l.add(2,"c");
l.add(3,"d");
System.out.println(l);
ListIterator li = l.listIterator();
while (li.hasNext()) {
Object n = li.next();
if (n.equals("b")) {
li.add("ee");//使用迭代器进行删除,不能使用集合对象
}
//System.out.println(n);
}
System.out.println(l);
}
}
List实现类
List接口实现类的分类:
-
ArrayList:数组方式实现元素存储,采用顺序存储,底层数据结构使数组结构,查询速度快,增删改慢,
-
LinkedList:节点(链表)的方式存储,每一个元素,就是一个节点,采用链式方式,底层使用链表结构,增删速度快,查询稍慢;
-
Vector:数组的方式实现,存储采用顺序,线程安全,效率低,底层是数组结构,Vector是线程同步的,所以它也是线程安全的。而ArratList是线程异步的,不安全。如果不考虑安全因素,一般Arralist效率较高;
ArrayList
常用的构造方法:
-
ArrayList(): 空参数构造,创建出来的集合,默认私有小数组容量为10
-
ArrayList(int capacity):通过执行构造方法初始化集合中小数组的容量
存储方式:
-
数组存储,顺序存储
-
查改快,增删慢
内存中元素都是紧挨着的,空间也是连续的,存储空间也是一样的,所以改查的时候可以快速定位元素
而加入数据时,因为元紧挨着,空间连续,每插入一元素,插入位置之后的元素都要往下移一位,效率很慢,删除则是反之,效率也差
package Test2;
import java.util.List;
import java.util.ListIterator;
import java.util.ArrayList;
import java.util.Iterator;
public class Tt {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add(1);
al.add(2);
al.add(3);
System.out.println(al);
ArrayList al2 = new ArrayList(20);
}
}
LinkedList
存储方式
-
节点实现,链式存储
-
每个元素都存储在一个节点中,节点中,不仅存储元素,而且还存储了下一个元素的地址
LinkedList存储元素的特点:增删快,查改慢
每个元素都有节点,要查元素时如果元素过多,查询的节点也多,效率就慢
而节点没有固定位置,每次加入新元素,把当前元素的地址修改即可完成插入,不用移动其他元素,效率更高
-
addFirst(Object obj):向头部添加一个缘故
-
addLast(Object o):向尾部添加一个元素
-
removeFirst():删除头部
-
removeLast():删除尾部
-
getFirst():获取头部元素
-
getLast():获取尾部元素
package Test2;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class Tt {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.addFirst("1");//向头部添加元素
list.addFirst("2");
System.out.println(list);
list.addLast("3");//向尾部添加元素
list.addLast("4");
System.out.println(list);
System.out.println(list.getFirst());//获取头部元素
System.out.println(list.getLast());//获取尾部元素
System.out.println(list.removeFirst());//删除头部尾部元素
System.out.println(list.removeLast());//调用删除方法,会返回当前删除的元素是哪一个
System.out.println(list);
}
}