java基础-- 集合框架入门 及 List集合
一、集合概述
1、为什么出现集合?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象进行操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
2、数组和集合同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。
3、集合类的特点:
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
二、 Collection体系
List: 元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList: 底层的数据结构使用的是数组结构。
特点:查询速度很快。但是增、删稍慢,线程不同步。
默认容量为10,以%50扩展
|--LinkedList: 底层使用的链表数据结构。
特点:增删速度很快,查询稍慢(因为依次查询),线程不同步。
|--Vector: 底层是数组数据结构,线程同步。
被ArrayList替代了,因为效率低。
默认容量为10,以%100延长。
Set:元素是无序,元素不可以重复。、
|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
|--TreeSet:
迭代
迭代是取出集合中元素的一种方式。
因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。
迭代器 Iterator的内部设计方式
把取出方式定义在集合内部,这样取出方式就可以直接访问集合内容的元素。
因此取出方式就被定义成了内部类。
而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容:
判断和取出,那么可以将这些共性抽取,这些内部类都符合一个规则,该规则是Iterator。
如何获取集合的取出对象呢?
通过一个对外提供的方法:iterator();
迭代注意事项:
1、迭代器在Collection接口中是通用的,它替代了Vector类中的Enumeration
枚举是Vector的特有取出方式。
2、迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException
3、迭代器的next方法返回值类型是Object,所以要记得类型转换。
集合共性方法演示代码:
import java.util.ArrayList; import java.util.Iterator; class CollectionDemo { public static void main(String[] args) { method_get(); } public static void method_get() { ArrayList al = new ArrayList(); // 1,添加元素。 al.add("java01");// add(Object obj); al.add("java02"); al.add("java03"); al.add("java04"); /* Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。 while(it.hasNext()) { sop(it.next()); } */ for (Iterator it = al.iterator(); it.hasNext();) { sop(it.next()); } } public static void method_2() { ArrayList al1 = new ArrayList(); al1.add("java01"); al1.add("java02"); al1.add("java03"); al1.add("java04"); ArrayList al2 = new ArrayList(); al2.add("java03"); al2.add("java04"); al2.add("java05"); al2.add("java06"); // al1.retainAll(al2);//取交集,al1中只会保留和al2中相同的元素。 al1.removeAll(al2);// 删除多个元素,al1中保留与al2中不相同的元素 sop("al1:" + al1); sop("al2:" + al2); } public static void base_method() { // 创建一个集合容器。使用Collection接口的子类。ArrayList ArrayList al = new ArrayList(); // 1,添加元素。 al.add("java01");// add(Object obj); al.add("java02"); al.add("java03"); al.add("java04"); // 打印原集合。 sop("原集合:" + al); // 3,删除元素。 // al.remove("java02"); // al.clear();//清空集合。 // 4,判断元素。 sop("java03是否存在:" + al.contains("java03")); sop("集合是否为空?" + al.isEmpty()); // 2,获取个数。集合长度。 sop("size:" + al.size()); // 打印改变后的集合。 sop(al); } public static void sop(Object obj) { System.out.println(obj); } }
三、 List集合
List:
List集合判断元素是否相同,依据是元素的equals方法。
特有方法:
凡是可以操作角标的方法都是该体系特有的方法。
因为底层的数据结构使用的是数组结构
1、 增删改查方法
增 add(index,element);
删 remove(index);
改 set(index,element); get(index):
查 addAll(index,Collection); int indexOf(obj): listIterator(); subList(from,to);
remove方法底层也是依赖于元素的equals方法
2、List集合特有的迭代器:ListIterator
它是Iterator的子接口。
3、ListIterator 出现的原因:
在迭代时,不可以通过集合对象的方法操作集合中的元素。
因为会发生并发修改异常:ConcurrentModificationException,所以在迭代器时,只能用迭代器的方式操作元素,可是Iterator方法是有限的,只能对
元素进行判断,取出,删除的操作,如果想要其他的操作如添加、修改等,就需要使用其子接口,ListIterator,该接口只能通过List集合的listIterator方法获取。
List集合共性方法、ListIterator演示代码:
import java.util.*; class ListTest { public static void sop(Object obj) { System.out.println(obj); } // List集合共性方法演示 public static void method() { ArrayList al = new ArrayList(); // 添加元素 al.add("java01"); al.add("java02"); al.add("java03"); sop("原集合是:" + al); // 在指定位置添加元素。 al.add(1, "java09"); // 删除指定位置的元素。 // al.remove(2); // 修改元素。 // al.set(2,"java007"); // 通过角标获取元素。 sop("get(1):" + al.get(1)); sop(al); // 通过list集合特有方法获取所有元素。 for (int x = 0; x < al.size(); x++) { System.out.println("al(" + x + ")=" + al.get(x)); } // 通过迭代器获取所有元素 Iterator it = al.iterator(); while (it.hasNext()) { sop("next:" + it.next()); } // 通过indexOf获取对象的位置。 sop("index=" + al.indexOf("java02")); // 获取指定区间的元素,包含头不包含尾 List sub = al.subList(1, 3); sop("sub=" + sub); } // 列表迭代器演示 public static void ListIteratorTest() { ArrayList al = new ArrayList(); // 添加元素 al.add("java01"); al.add("java02"); al.add("java03"); sop(al); ListIterator li = al.listIterator(); // sop("hasPrevious():"+li.hasPrevious()); while (li.hasNext()) { Object obj = li.next(); if (obj.equals("java02")) // li.add("java009"); li.set("java006"); } //倒序遍历 while (li.hasPrevious()) { sop("pre::" + li.previous()); } // sop("hasNext():"+li.hasNext()); // sop("hasPrevious():"+li.hasPrevious()); sop(al); /* // 在迭代过程中,使用集合的方法添加或者删除元素。 Iterator it = al.iterator(); while (it.hasNext()) { Object obj = it.next(); if (obj.equals("java02")) // al.add("java008"); //使用了集合的方法,会出现并发修改异常 it.remove(); // 只是将java02的引用从集合中删除了。 // 当读到java02时,obj获取到java02的引用,remove只是将集合中的引用移除了, // 但元素还在内存当中,其引用正在被obj使用,所以java02还能够被打印, sop("obj=" + obj); } sop(al); */ } } class ListDemo{ public static void main(String[] args) { ListTest.method(); ListTest.ListIteratorTest(); } }
四、 LinkedList集合
LinkedList:特有方法:
1> addFirst() addLast();
2> getFirst();getLast();
获取元素,但不删除元素。
如果集合中没有元素,会出现 NoSuchElementException
3> removeFirst(); removeLast();
获取元素,但是元素被删除。
如果集合中没有元素,会出现 NoSuchElementException
在JDK1.6出现了替代方法:
1> offerFirst()、offerLast();
2> peekFirst()、peekLast();
获取元素,但不删除元素。
如果集合中没有元素,会返回null。
3> pollFirst()、pollLast();
获取元素,但是元素被删除。
如果集合中没有元素,会返回null。
LinkedList方法示例代码:
class LinkedListDemo { public static void main(String[] args) { LinkedList link = new LinkedList(); link.addLast("java01"); link.addLast("java02"); link.addLast("java03"); link.addLast("java04"); //sop(link); //sop(link.getFirst()); java01 //sop(link.getFirst()); java01 //sop(link.removeFirst()); java01 //sop(link.removeFirst()); java02 //sop(link.getLast()); //sop("size="+link.size()); //使用removeLast,获取元素 while(!link.isEmpty()){ sop(link.removeLast()); } } public static void sop(Object obj){ System.out.println(obj); } }
使用LinkedList模拟一个堆栈或者队列数据结构示例代码(重点):
堆栈:先进后出
队列:先进先出
1、思路:对原有LinkedList集合的方法进行封装,对外暴露便于识别的方法去操作。
2、这种封装开发方式的意义:
为了创建一些和项目更贴近的一些方法,将原有的容器封装进我们的描当中。
使用原有列表容器的方法,对原有列表容器进行封装,并起一些和项目相关的名称,对外提供更易识别、更有意义的名称来进行操作。
import java.util.*; class MyQueue { private LinkedList link; MyQueue() { link = new LinkedList(); } public void myAdd(Object obj) { link.addFirst(obj); } //只需改变取出的顺序,即可完成进行队列与堆栈的变换 public Object myGet() { return link.removeLast(); //队列 :先进先出 // return link.removeFirst(); //堆栈 :先进后出 } public boolean isNull() { return link.isEmpty(); } } class LinkedListTest { public static void main(String[] args) { MyQueue mq = new MyQueue(); mq.myAdd("java01"); mq.myAdd("java02"); mq.myAdd("java03"); mq.myAdd("java04"); while (!mq.isNull()) { System.out.println(mq.myGet()); } } }
ArrayList练习一:去除ArrayList集合中的重复元素
关键:在往ArrayList集合中存入数据的时候进行判断是否已经存在
注意:在使用迭代的时候next调用一次,hasNext就要判断一次,以免出现NoSuchElementException异常
import java.util.ArrayList; import java.util.Iterator; class SingleElement { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java01"); al.add("java02"); al.add("java01"); // al.add("java03"); //在迭代时循环中next调用一次,就要让hasNext判断一次。 否则容易出现NoSuchElementException异常 Iterator it = al.iterator(); while(it.hasNext()) { //元素为偶数可以,奇数就会出现NoSuchElementException sop(it.next()+"...."+it.next()); } sop(al); al = singleElement(al); sop(al); } public static ArrayList singleElement(ArrayList al) { // 定义一个临时容器。 ArrayList newAl = new ArrayList(); for(Iterator it = al.iterator(); it.hasNext();){ Object obj = it.next(); if (!newAl.contains(obj))//判断是否已经存有相同元素 newAl.add(obj); } return newAl; } }
ArrayList练习二:存入人对象(避免存入相同元素)
将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存人对象,同姓名同年龄,视为同一个人,为重复元素。
思路:
1、对人描述,将数据封装进人对象。
2、定义容器,将人存入。
3、取出。
说明:List集合判断元素是否相同,依据是元素的equals方法。
所以为了让对象使用自己定义的方法比较对象时,应该覆盖equals方法。
class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } public boolean equals(Object obj) { if (!(obj instanceof Person)) return false; Person p = (Person) obj; // System.out.println(this.name+"....."+p.name); return this.name.equals(p.name) && this.age == p.age; } public String getName() { return name; } public int getAge() { return age; } } class Tool { public static ArrayList singleElement(ArrayList al) { // 定义一个临时容器。 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while (it.hasNext()) { Object obj = it.next(); if (!newAl.contains(obj))// contains底层调用的是equals newAl.add(obj); } return newAl; } } class ArrayListTest2 { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); // al.add(new Demo()); al.add(new Person("lisi01", 30));// al.add(Object obj)相当于:Object obj = new Person("lisi01",30); // al.add(new Person("lisi02",32)); al.add(new Person("lisi02", 32)); al.add(new Person("lisi04", 35)); al.add(new Person("lisi03", 33)); // al.add(new Person("lisi04",35)); al = Tool.singleElement(al); // remove方法底层也是依赖于元素的equals方法。 // sop("remove 03 :"+al.remove(new Person("lisi03",33))); for (Iterator it = al.iterator(); it.hasNext();) { Person p = (Person) it.next();// 由于it.next()返回值为Object,所以需强转以便使用Person的特有方法 sop(p.getName() + " : " + p.getAge()); } } }