JAVA类集框架
一.基本概念
在讲解类集概念前,先来思考这样一个问题, 如果现在要保存一组对象, 按照之前的做法则只能使用对象数组,一但是使用对象数组操作本身有一个限制, 就是数组有长度的限制:而通过一些数据结构的操作,如链表,则可以完成动态对象数组的操作,但是这些如果全部由开发人员来做,则肯定是比较麻烦的。
类集框架恰好解决了 上面的难题,所谓类集就是一个动态的对象数组,是对一些实现好的数据结构进行了包装,这样在使用时就会非常方便,而且最重要的是类集框架本身不受对象数组的长度限制。
注:数组最大的缺点之一就是会受到长度的限制。
二.类集框架的组成部分
三.被设计成的类集框架有以下的几个特性
(1)框架必须是高性能的。对基本类集(动态数组,连接表,树和散列表)的实现须是高效率的。一般很少需要人工对这些“数据引擎”编写代码。
(2)框架必须允许不同类型的类集以相同的方式和高度互操作方式工作。
(3)类集必须是容易扩展和修改的。所以很多被设计成一组接口方便具体类实现。(可以参考里氏替换原则)
四.类集框架的一些主要的接口和一些实现类
类集框架:jdk提供的一系列类和接口,位于java.util包当中,主要用于存储和管理对象,主要分为三大类:集合、列表和映射。
集合Set:用于存储一系列对象的集合。无序、不允许重复元素。
列表List:用来存储有顺序的一组数据的集合。有序
映射Map:以键值对的方式进行数据存储的集合。
Collection接口是类集单值保存的最大父接口。
Map接口是类集键值对保存的最大父接口。
五.一些经常使用的接口的方法
Collection接口
定义如下:
public interface Collection<E> extends lterable<E>.
(Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,且使得所有实现了Collection接口的具体类都能够迭代输出)
一般运用向上转型为Collectiion实例化对象。
1 public boolean add(E e):添加一个元素
2 public void clear():清空集合中所有的元素
3 public boolean remove(E e):移除集合中指定的元素
4 public boolean contains(E e):检查集合中是否包含指定的对象
5 public boolean isEmpty():判断集合是否为空
6 public void size():判断集合中元素的个数
7 public Object[] toArray():把集合元素存储到数组中
List接口
注:JAVA中判断是否有重复的内容或者对象是通过equals和hashcode来判断的,所以一般自定义的类必须的覆写Object类中的这两个方法 。 一般排序时还要覆写compareTo()方法。
定义如下:
public interface List<E>extends Collection<E>.
List接口,其下面主要实现类有Vector集合,ArrayList集合,LinkedList集合,底层实现方式有数组,也有链表,它有如下特点:
(1)有序的集合,即存储和取出元素的顺序相同
(2)允许存储重复的元素
(3)有索引,可以使用普通的for循环遍历
List接口扩展了许多Collection的方法,下面是一些常用的方法。
1.public void add(int index,E element): 在指定位置增加元素
2.E get(int index): 返回指定位置的元素
3.public int indexOf(Object o):返回指定位置的元素
4.public ListIterator<E>listIterator():为ListIterator接口实例化。
5.public E remove(int index):按指定的位置删除元素。
新的子类:ArrayList (很常用)
ArrayList 是List子类,可以直接通过对象的多态性为List接口实例化。
新的子类:LinkedList
LinkList表示的是一个链表的操作类,即Java中已经为开发者提供好了一个链表程序,开发者可以直接使用,而不用再重新开发。
常用的方法:
1.public void addFirst(E o):在链表开头增加元素。
2.public void addLast(E o);在链表结尾增加元素。
3.public E removeFirst();删除链表的第一个元素。
4.public E removeLast();删除链表的最后一个元素。
Set接口
1.Set接口是无序的。
2.Set是继承于Collection
的接口。它是一个不允许有重复元素的集合。
3.Set可以存储null值,但是null不能重复。
Set接口其实和List接口没有太大的区别。但Set接口的主要方法与Collection是一致的,也就是说Set接口并没有对Collection接口进行扩充。
Set接口的常用子类:
1.HashSet(散列存放):
里面不能存放重复元素,而且采用散列存放,所以没有顺序。
2.TreeSet
有序排序,如果要排序自定义的类,则必须实现Comparable接口才可以正常使用,且覆写compareTo()方法。
Map接口
上面的接口都属于单值的操作,即每次只能操作一个对象,而Map与它们不同,每次操作的都是一对对象,即二元偶对象,Map中的每个元素都使用“Key——>value"的形式存储在集合中。
定义如下:
public interface Map<k,v>
Map接口中的方法
【注意】:Map集合通过entrySet()方法转换成Set集合,Set集合中元素的类型是:Map.Entry<K,V>。Map.Entry<K,V>:和String一样是一个类型的名字,是Map中的静态内部类(内部接口)
Map集合的继承结构
【注意】:非线程安全的类采用异步处理方式,性能更高。而线程安全的类采用同步处理方式,性能较低。
使用Map接口的注意事项
对于Map接口来说,其本身是不能直接使用迭代(如Iterator, foreach) 进行输出的,因为Map中的每个位置存放的是一对值(key > value),而Iterator中每次只能找到一个值。所以,如果非要使用送代进行输出,则必须按照以下的步骤完成(以Tertor输出方法为例)。
(1)将Map的实例通过entrySet0方法变为Set接口对象。
(2)通过Set接口实例为Iterator实例化。
(3)通过Iterator迭代输出,每个内容都是Map. Entry的对象。
(4)通过Map.Entry进行key ——> value的分离。
Map中的每对数据都是通过Map.Entry保存的,所以如果最终要进行输出的话也应该使用Map.Entry完成。
六.集合的输出
在类集中提供了4中常见的输出方式
1.Iterator:迭代输出,是使用最多的输出方式。
2.ListIterator:是Iterator的子接口,专门用于输出List中的内容。
3.Enumeration:是一个旧的接口,功能与Iterator类似。
4.foreach:JDK1.5之后提供的新功能,可以输出数组或集合。
迭代输出Iterator
迭代模式指的是依据指针依次判断是否有数据,如果有数据则进行数据的取出。
定义如下:
public interface Iterator<E>
Iterator接口中的常用方法:
1.public boolean hasNext() ; 判断是否有下一个值。
2.public E next() ; 取出当前元素。
3.public void remove() ; 移除当前元素。
import java.util.*;
public class TestIterator {
public static void main(String[] args) {
ArrayList<String> a = new ArrayList<String>();
a.add("aaa");
a.add("bbb");
a.add("ccc");
System.out.println("Before iterate : " + a);
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String t = it.next();
if ("bbb".equals(t)) {
it.remove();
}
}
System.out.println("After iterate : " + a);
}
}
运行结果:
【注意】正常情况下,一个集合要把内容交给Iterator输出,但是集合操作也存在一个remove()方法,如果在使用Iterator输出时,由集合调用自身的删除方法,运行时也会错误。
当内容被删除之后就终止了。这就是因为集合本身的内容被破坏掉了,所以迭代将出现错误停止输出。
import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Iterator; public class MapDemo01 { public static void main(String[] args) { Map<String,String> map=null; map = new HashMap<>(); map.put("mldn","www.mldn.cn"); map.put("zky","2020110261"); Set<Map.Entry<String,String>>allset=null; allset = map.entrySet(); Iterator<Map.Entry<String,String>> iter=null; iter=allset.iterator();
//下面的经典的迭代输出格式 while (iter.hasNext()){ Map.Entry<String,String> me=iter.next(); System.out.println(me.getKey()+"-->"+me.getValue()); } } }
运行结果:
双向迭代输出ListIterator
ListIterator是Iterator的子接口,主要作用是为List接口实现双向迭代。
主要添加方法如下;
1.public boolean hasPrevious();判断是否有上一个元素
2.public E previous();取出当前元素
3.public int nextIndex();取出下一个元素的索引号
4.public int previousIndex();返回上一个元素的索引号
双向迭代
class ListIteratorDemo01{ public static void main(String[] args) { List<String> all = new ArrayList<>(); all.add("hello"); all.add("_"); all.add("world"); ListIterator<String> iter = all.listIterator(); System.out.print("由前向后输出"); while (iter.hasNext()){ System.out.print(iter.next()+"、"); } System.out.print("\n由后向前输出"); while (iter.hasPrevious()){ System.out.print(iter.previous()+"、"); } } }
运行结果:
上面的程序实现了双向的迭代输出,但是此种输出方式只有List接口才可以做到。
foreach输出格式
for(类 对象 :集合){
//集合操作
}
此方法与数组的foreach格式一样。
class ListIteratorDemo01{ public static void main(String[] args) { List<String> all = new ArrayList<>(); all.add("hello"); all.add("_"); all.add("world"); for(String str : all){ System.out.print(str+"、"); } } }
Enumeration接口
Enumeration已经被淘汰了,此接口跟Iterator接口差不多,但Iterator接口中有删除数据的方法,且一些方法名称更短。
七.集合工具类Collections
1.public static void swap(List list, int i, int j) :将指定列表中的两个索引进行位置互换
2.public static void sort(List<T> list) :按照列表中元素的自然顺序进行排序
【注意】如果是要排序一个自定义的类,则一定要实现Comparable接口,否则会出现类型转换异常
3.public static void shuffle(List list):随机置换
4.public static void reverse(List list) :反转
5.public static void fill(List list, Object obj) :使用指定的对象填充指定列表的所有元素
6.public static void copy(List dest, List src) :是把源列表中的数据覆盖到目标列表
7.public static int binarySearch(List list, Object key) 使用二分查找法查找指定元素在指定列表的索引位置
常量
1.public static final List EMPTY_LIST 返回一个空的List集合
2.public static final List EMPTY_SET 返回空的Set集合
3.public static final List EMPTY_MAP 返回空的Map集合
可以观察到此接口中的方法和常量全是static定义的,所以可以直接通过类实现,而不需要实例化对象。
八.Stack类
Stack是栈;特点是:先进后出。
(如在浏览器中存在的一个“后退”按钮,每次后退都是后退到上一个页面,这实际上就是一个栈的应用,采用就是先进后出的操作)
Stack类的一些方法;
public E push(E item) 把项压入堆栈顶部。
public E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。
public E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。
public boolean empty() 测试堆栈是否为空。
public int search(Object o) 返回对象在堆栈中的位置,以 1 为基数。
九.本章类集框架要点
1.类集的目的是用来创建动态的对象数组操作。
2.Collection接口是类集中的最大单值操作的父接口,但是一般的开放中不会直接使用,而是使用List接口或Set接口。
3.List接口扩展了Collection接口,里面的内容是允许重复的。其常用的子类:ArrayList和Vector,在开发中ArrayList性能较高,为异步处理。而Vecter性能较低,为同步处理。
4.对象是否是同一个主要是依靠Object类中的eaquals()和hashCode()方法来区分是否是同一个对象。
5.Set接口的常用子类有HashSet(散列存放,无序)和TreeSet(顺序存放,有序,使用Comparable接口进行排序操作)。
6.List集合可以使用ListIterator接口进行双向的输出操作。
7.Map接口中存放的是一对内容,采用键值对的方式存储,且每一个“Key->value”都是一个Map.Entry对象的实例,如果要输出则必须将其转换为Set接口对象,然后通过Iterator实例化输出。
8.类集中提供了Collections工具类完成了类集的相关操作。
9.使用类集可以方便的表示出一对多及多对一的关系。即在一个类中的属性再定义相关类型的类集。