集合框架一
Collection:是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
与Collection很容易在一起说的是Collections,java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
看集合对象的小技巧:
集合分体系:List Set
子类对象的后缀名是所属体系,前缀名是数据结构名称。
List:新出的子类都是以List结尾的,通常都是非同步的。
|-----ArrayList:看到array,就知道数组,查询速度快。
|-----LinkedList:看到link,就知道链表,增删速度快。
Set:
|-----HashSet:看到hash,就知道哈希表,查询速度更快,并想到元素唯一,通过hashCode(),equals方法
|-----TreeSet:看到tree,就知道二叉树,可以排序,排序想到Comparable-compareTo Comparator--compare方法。
ArrayList,LinkedList
Collection:
|----List:有序的,带索引的,通过索引就可以精确的操作集合中的元素,元素时可 以重复的。List提供了增删改查操作。
增加add(element) add(index,element)
删除remove(element) remove(index)
修改set(index,element)
查询get(index)
|---Vector:可以增长的数组结构。同步的。
|---ArrayList:是数组结构,长度是可变的(创建新数组+复制数组),查询速度很快,增删较慢,不同步的。
|---LinkedList:是链表结构,不同步的,增删速度很快,查询速度较慢。
可用于实现堆栈,队列。
堆栈:先进后出First in Last Out FILO
队列:先进先出 First in First Out FIFO
List可以存储重复元素的,如果需求中要求容器中的元素必须保证唯一性。
|----Set:不包含重复元素的集合,不保证而且方法和Collection一致。Set集合取出元素的方法只有一种:迭代器。
|--HashSet:哈希表结构,不同步,保证元素唯一性的方式依赖于:hashCode(),equals()方法。查询速度快。
|--TreeSet :可以对Set集合中的元素进行排序。使用的是二叉树结构。
保证元素唯一性: 使用的对象比较方法的结果是否为0,如果是0就视为相同元素不存。
元素的排序比较有两种方式:
1.元素自身具备自然排序,或者具备的自然排序不是所需要的,这时只能用第二种方式。
2.比较器排序,其实就是在创建TreeSet集合时,在构造函数中指定具体的比较方式。需要定义一个类实现Comparator接口,重写compare方法。
到此为止:再往集合中存储对象时,通常该对象都需要覆盖hashCode,equals,同时实现Comparale接口,建立对象的自然排序。通常还有一个方法也会复写toString();
利用ArrayList去重复问题:
[html] view plaincopy
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("itcast1");
list.add("itcast2");
list.add("itcast1");
list.add("itcast2");
list.add("itcast1");
list.add("itcast2");
getSingleElement(list); //取出重复元素
System.out.println(list);
}
/*
* 案例:去除List集合中的重复元素
*
* 思路:1.先创建一个临时容器,用于存储唯一性的元素。
* 2.遍历原容器,将遍历到元素放到临时容器中去判断,是否存在
* 3.如果存在,不存储到临时容器中。如果不存在,不存储到临时容器中。
* 4.遍历结束后,临时容器中国存储的就是唯一性的元素。
* 5.如果需要将这些唯一性的元素保留到原容器清空,将临时容器中等个元素添加到元容器中即可。
*
*/
public static List getSingleElement(List list){
//1.创建一个临时容器
List temp = new ArrayList();
//2.遍历原容器。
for(Iterator it = list.iterator(); it.hasNext();){
Object obj = it.next();
//对遍历到的每一个元素都到临时容器中去判断是否包含。
if(!temp.contains(obj)){ //如果不存在
temp.add(obj);
}
}
//唯一性的元素已经被记录到临时容器中,清空原容器中的元素。
list.clear();
//把临时容器中的元素添加到原容器中。
list.addAll(temp);
return temp;
}
}
其中LinkedList常用的方法:addFirst() addLast() getFirst() getLast() removeFirst() removeLast()
可以发现在LinkedList中特有的方法命名:围绕头和尾展开定义的。First Last
一道面试题:
[html] view plaincopy
import java.util.LinkedList;
public class LinkedListTest {
public static void main(String[] args) {
/*
* 面试题:用LinkedList模拟一个堆栈或者队列数据结构。
* 创建一个堆栈或者队列数据结构对象。
*/
//创建一个队列对象
Queue queue = new Queue();
//往队列中添加元素
queue.addQueue("itcast1");
queue.addQueue("itcast2");
queue.addQueue("itcast3");
queue.addQueue("itcast4");
while(!queue.isNull()){
System.out.println(queue.GetQueue());
}
}
}
/**
*定义一个队列数据结构。Queue
*/
class Queue{
//封装了一个链表数据结构。
private LinkedList link;
/*
* 队列初始化时,对链表对象初始化。
*/
Queue(){
link= new LinkedList();
}
/*
*队列的添加元素的功能
*/
public void addQueue(Object obj){
//内部使用的是链表的方法
lin
* 判断队列中元素是否为空,没有元素就是真的
*/
public boolean isNull(){
return link.isEmpty();
}
}k.addFirst(obj);
}
/*
* 队列的获取方法
*/
public Object GetQueue(){
return link.removeLast();
}
哈希表
通过对哈希表的分析:存储元素时,先调用了元素对象的hashCode()方法,而每个学生对象都是新建立的对象,所以hashCode值都不相同,也就不需要判断equals了。
默认equals比较两者的hashCode
在HashSet对象中查找数据,是根据数据的hashCode进行换算,确定在哪个区域。
如果两个对象equals一样,最后让它们的hashCode也一样,但如果存在ArrayList中,hashCode是没有用处的。
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet的哈希值就不一样了,这样即使使用该对象的当前引用作为参数检索该对象,也找不到了,这将导致无法从HashSet中单独删掉这个对象,造成内存泄露。
TreeSet篇:
TreeSet的add方法内部最终实现:需要将元素转成Comparable类型。因为这个类型具备排序的能力。这个类型中有一个专门为排序提供了一个compareTo方法。
如果需要对象有比较排序的功能,需要让对象扩展功能,实现Comparable接口。
提示:在比较时,必须明确主次。主要条件相同,继续比较次要条件。(这里可以用三目运算符)
在编程中会遇到ConcurrentModificationException异常
ConcurrentModificationException异常:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
引发此异常的原因:在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。
解决思路:在迭代时,不要使用集合的方法操作元素。 此时应该想到Iterator有一个子接口ListIterator可以完成该问题的解决,通过List接口中的listIterator()就可以获取。该列表迭代器只用List接口有。
小知识点补充:
foreach:其实就是增强for循环。
格式:for(数据类型 变量 : Collection集合or数组){}
用途: 遍历Collection和数组。通常只能遍历元素,不要再遍历的过程中做对集合元素的操作。
与之前的for循环有什么区别?
新的for循环必须有被遍历的目标。目标只能是Collection或者是数组。
建议:遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行操作,使用老式for循环可以通过角标操作。 |
|