- java三大工具类:java 集合框架,java并发框架,java IO流框架
- 为了保存数量不确定的数据,以及保存具有映射关系的数据,java提供了集合类。
- java集合框架从根接口来说,分为两类:
列表集合,只包含value。Collection接口及它的子类。
映射表集合,包含key和value。Map接口及它的子类。
一.Collection接口
- Collection接口继承自Iterable接口:
public interface Collection<E> extends Iterable<E>
- Iterable接口中只有一个方法:
Iterator<T> iterator()
,返回的是一个迭代器
//两个接口
public interface Iterator
{
public abstract boolean hasNext();
public abstract Object next();
}
public interface Iterable
{
Iterator iterator();
}
//Collection接口及其实现类之间关系
public interface Collection extends Iterable{}
public interface List extends Collection{}
public class ArrayList implements List(){}
3.Iterator接口:
Iterator主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。其本身并不提供盛装对象的能力。Iterator必须依附于Cllection对象,如果有一个Iterator对象,则必然有一个与之关联的Colletion对象。
Iterator接口的方法:
方法 | 说明 |
---|---|
boolean hasNext() | 如果被遍历的几何元素还没有被遍历完,则返回true. |
Object next() | 返回集合里的下一个元素 |
void remove() | 删除集合里上一次next方法返回的元素 |
Iterator通过hasNext()和next()方法来迭代访问Collection集合中的对象。
4. Collection接口的方法:
方法功能 | 方法 | 说明 |
---|---|---|
添加 | boolean add(Object o) | 该方法用于向集合里添加一个元素。如果集合对象被添加操作改变了,则返回true。 |
添加 | boolean addAll(Collection c) | 该方法把集合c里的所有元素添加到指定集合里。如果集合对象被添加操作改变了,则返回true。 |
删除 | void clear() | 清除集合里的所有元素,将集合长度变为0。 |
删除 | boolean remove(Object o) | 删除集合中的指定元素o,当集合中包含了一个或多个元素o时,这些元素将被删除,该方法将返回true。 |
删除 | boolean removeAll(Collection c) | 从集合中删除集合c里包含的所有元素(相当于用调用该方法的集合减集合c),如果删除了一个或一个以上的元素,则该方法返回true。 |
判断 | boolean contains(Object o) | 返回集合里是否包含指定元素。 |
判断 | boolean containsAll(Collection c) | 返回集合里是否包含集合c里的所有元素。 |
判断 | boolean isEmpty() | 返回集合是否为空。当集合长度为0时返回true,否则返回false。 |
获取 | Iterator iterator() | 返回一个Iterator对象,用于遍历集合里的元素。 |
交集 | boolean retainAll(Collection c) | 从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集),如果该操作改变了调用该方法的集合,则该方法返回true。 |
长度 | int size() | 该方法返回集合里元素的个数。 |
集合转换为数组 | Object[] toArray() | 该方法把集合转换成一个数组,所有的集合元素变成对应的数组元素。 |
注意:
- 这些方法来自于API文档,无需硬性记忆,集合类就像容器,容器的功能,无非就是添加对象,删除对象,清空容器,判断容器是否为空等。
- Collection接口是Set接口和List接口的父接口,该接口中的方法可用于操纵Set集合和List集合。
具体测试:
(1)创建集合对象
- Collection c = new ArrayList();
- Collection c1 = new ArrayList();
Collection为根接口,只包含value,但是由于数据存储方式的不同,java又提供了具体的子接口即Set接口和List接口,由于接口不能实例化,所以需要具体实现类来创建对象,ArrayList()是List集合的一个具体实现类,可用于创建集合对象。
(2)boolean add(E e)添加一个元素向集合中添加元素
- c.add(“郑爽”);
- c.add(7);
- c.add(“hello”);
- c1.add(“hh”);
- c1.add(“hello”);
虽然集合中不可存放基本类型的数据,但是java支持自动装箱。
ArrayList方法中add()方法的源码:
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
由源码可以看到,add方法返回的是一个boolean类型的值,且恒为true,因此不用判断是否添加成功,即不用输出返回结果,直接添加即可。
(3)boolean remove(Object o)移除一个元素移除集合中的一个元素
- c.remove(“郑爽”);
(4)void clear()移除此集合中的所有元素
- c.clear();
(5)boolean contains(Object 0)判断集合中是否包含指定的元素
- c.contains(“hello”)
(6)boolean isEmpty()判断集合是否为空
- c.isEmpty()
(7)int size()返回此集合中的元素数
- c.size()
(8)boolean addAll(Collection c)添加一个集合的元素
- c.addAll(c1)
将集合c2中的元素添加到集合c1中
(9)boolean removeAll(Collection c)移除一个集合的元素
- c.removeAll(c1)
将c1集合内含有的c2集合内的元素移除,只要有一个元素移除成功就返回true.
(10)boolean containsAll(Collection c)判断及集合中是否包含指定的集合元素
- c.containsAll(c1)
只有c1中包含集合c2中所有的元素才返回true.
(11)boolean retainAll(Collection c)两个集合都有的元素
- c.retainAll(c1)
交集后的集合元素保存在c1中,c2不变,返回的结果表示c1中的值是否发生改变,改变则为true,没改变则为false.
(12)Object[] toArray()返回包含此集合中所有元素的数组。
Object[] objs = c.toArray();
for(int x=0;x<objs.length;x++)
{
System.out.println(objs[x]);
}
(13)Iterator iterator()(重点)迭代器,集合的专用遍历方法
//通过集合对象获取迭代器对象,iterator()是Collection的父接口中的方法。
Iterator it = c.iterator();
while(it.hasNext())
{
//向下转型
String s = (String)it.next();
System.out.println(s);
}
二.List接口:
- List接口是Collection接口的子接口,可以使用Collection接口中的全部方法。
- List集合的特点:元素有序(存储和取出的元素一致),可以重复,集合中每个元素都有其对应的索引,可以通过索引来访问指定位置的集合元素。
- List集合的特有方法:
由于List集合是有序集合,所以List集合里添加了一些根据索引来操作元素的方法。
方法功能 | 方法 | 说明 |
---|---|---|
添加 | void add(int index, Object element) | 将元素element插入到List集合的index处。 |
添加 | boolean addAll(int index, Collection c) | 将集合c所包含的所有元素都插入到List集合的index处。 |
获取 | Object get(int index) | 返回集合index索引处的元素。 |
获取 | int indexOf(Object o) | 返回对象o在List集合中第一次出现的位置索引。 |
获取 | int lastIndexOf(Object o) | 返回对象o在List集合中最后一次出现的位置索引。 |
删除 | Object remove(int index) | 删除并返回index索引处的元素。 |
修改 | Object set(int index, Object element) | 将index索引处的元素替换成element对象,返回新元素。 |
列表迭代器 | ListIterator listIterator(int index) | List集合特有的迭代器 |
具体测试:
(1)创建集合对象
- List list = new ArrayList();
(2)添加元素
- list.add(“ll”);
- list.add(“kk”);
- list.add(“mm”);
(3)void add(int index, E element)在指定的位置添加元素。
- list.add(1,“nn”);
(4)Object get(int index)获取指定位置的元素
- list.get(1)
(5)Object remove(int index):根据索引删除元素,返回被删除的元素
- list.remove(1),返回kk
(6)Object set(int index,Object element):根据索引修改元素,返回被修改的元素
- list.set(1,“vv”),返回ll
4 .List集合特有的遍历功能:Size()方法和get()方法结合。
public static void main(String[] args)
{
//创建集合对象
List list = new ArrayList();
//添加元素
list.add("ll");
list.add("kk");
list.add("mm");
for(int x=0;x<list.size();x++)
{
System.out.println(list.get(x));
}
}
5.ListIterator :List集合特有的迭代器
例:有一个集合,判断里面有没有一个"world"元素,如果有,就添加一个"javaee"元素
当使用iterator迭代访问Collection集合中的元素时,Collection集合中的元素不能改变,只能通过Iterator集合中的remove()方法删除next()方法返回的集合元素才可以,否则将引发ConcurrentModificationException异常,两种解决方法:
- 迭代器迭代元素,迭代器修改元素
元素是跟在刚才迭代的元素后面的 - 集合遍历元素,集合修改元素
元素放在最后添加的。
public static void main(String[] args)
{
//创建List对象
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
//方式1:迭代器迭代元素,迭代器修改元素
//Iterator迭代器没有添加功能,所以使用其子接口ListIterator
ListIterator lit = list.listIterator();
while(lit.hasNext())
{
String s = (String)lit.next();
if("world".equals(s))
{
lit.add("javase");
}
}
System.out.println(list);//[hello, world, javase, java]
//方式2:集合遍历元素,集合修改元素
for(int x=0;x<list.size();x++)
{
String s = (String)list.get(x);
if("world".equals(s))
{
list.add("javase");
}
}
System.out.println(list);//[hello, world, java, javase]
6.List集合存储字符串并遍历
public static void main(String[] args)
{
//创建集合对象
List list = new ArrayList();
//创建字符串并将字符串添加到集合对象中
list.add("hh");
list.add("kk");
list.add("ff");
//通过集合对象获取迭代器对象
Iterator it = list.iterator();
while(it.hasNext())
{
String s = (String)it.next();
System.out.println(s);
}
}
三.List接口的具体实现类
1.List接口实现类的特点:
- ArrayList:
底层数据结构是数组,查询快,增删慢
线程不安全,效率高 - Vector:
底层数据结构是数组,查询快,增删慢
线程安全,效率底 - LinkedList:
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
2.ArrayList:
例:存储字符串并遍历
public static void main(String[] args)
{
//创建集合对象
ArrayList array = new ArrayList();
//创建元素对象,并添加元素
array.add("hh");
array.add("kk");
array.add("ll");
//通过迭代器遍历集合
Iterator it = array.iterator();
while(it.hasNext())
{
String s = (String)it.next();
System.out.println(s);
}
//通过数组方式遍历集合
for(int x=0;x<array.size();x++)
{
String s = (String)array.get(x);
System.out.println(s);
}
3.Vector:
Vector是一个很古老的集合,那时候java还没有提供系统的集合框架,所以Vector提供了一些方法名很长的方法,JDK1.2以后,java提供了系统的集合框架,就将Vector改为实现List的接口,作为List的实现之一,从而导致Vector里面有一些功能重复的方法。总之Vector有很多缺点,很少使用。
Vector功能 | 方法 | 替换方法 |
---|---|---|
添加 | void addElement(Object obj) | add() |
获取 | Object elementAt(int index) | get() |
迭代器 | Enumeration elements() | Iterator |
判断 | boolean hasMoreElements() | hasNext() |
获取 | nextElement() | next() |
public static void main(String[] args)
{
//创建集合对象
Vector v = new Vector();
//添加元素
v.addElement("hello");
v.addElement("world");
v.addElement("java");
//遍历
for(int x=0;x<v.size();x++)
{
String s = (String)v.elementAt(x);
System.out.println(s);
}
Enumeration en = v.elements();//返回的是实现类的对象
while(en.hasMoreElements())
{
String s = (String)en.nextElement();
System.out.println(s);
}
}
3.LinkedList:
LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合中的元素时性能较差,但是在插入删除元素时,性能较好。
特有方法:
功能 | 方法 | 说明 |
---|---|---|
添加 | void addFirst(Object e) | 将指定元素添加到此列表的开头 |
添加 | addLast(Object e) | 将指定元素添加到此列表的结尾 |
获取 | Object getFirst() | 返回此列表的第一个元素 |
获取 | Object getLast() | 返回此列表的最后一个元素 |
删除 | Object removeFirst() | 移除并返回此列表的第一个元素 |
删除 | Object removeLast() | 移除并返回此列表的最后一个元素 |
public static void main(String[] args)
{
//创建集合对象
LinkedList link = new LinkedList();
//添加元素
link.add("hello");
link.add("world");
link.add("java");
//public void addFirst(Object e)将指定元素插入此列表的开头
link.addFirst("hh");
//public void addLast(Object e)将指定元素添加到此列表的结尾。
link.addLast("ll");
//public Object getFirst()返回此列表的第一个元素。
System.out.println(link.getFirst());
//public Object getLast()返回此列表的最后一个元素。
System.out.println(link.getLast());
//public Object removeFirst()移除并返回此列表的第一个元素。
System.out.println(link.removeFirst());
// public Object removeLast()移除并返回此列表的最后一个元素。
System.out.println(link.removeLast());
}
4.LikedList练习:
例:请用LinkedList模拟栈数据结构的集合,并测试
例:ArrayList去除集合中字符串的重复值(字符串的内容相同)
例:ArrayList去除集合中自定义对象的重复值
四.泛型:
1.泛型的引入:
Java集合有个缺点——当我们把一个对象“丢进”集合里后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型(其运行时类型没变)。因此取出集合元素后通常还需要进行强制类型转换。这种强制类型转换既增加了编程的复杂度,也可能引发ClassCastException异常。
public class ListErr
{
public static void main(String[] args)
{
// 创建一个只想保存字符串的List集合
List strList=new ArrayList();
strList.add("ff");
strList.add("hh");
strList.add("jj");
// “不小心”把一个Integer对象“丢进”了集合
strList.add(5);
for (int i=0; i < strList.size() ; i++ )
{
// 因为List里取出的全部是Object,所以必须进行强制类型转换
// 最后一个元素将出现ClassCastException异常
String str=(String)strList.get(i);
}
}
}
注意:程序引发ClassCastException异常,因为想把一个Integer对象转换为String类型。
2.泛型的使用地方:
如果类,接口,抽象类后面跟E就要使用泛型,一般来说在集合中使用
例:用ArrayList存储字符串元素并遍历
public static void main(String[] args)
{
//用ArrayList存储字符串元素并遍历,用泛型改进代码
ArrayList<String> array = new ArrayList<String>();
//添加元素
array.add("hello");
array.add("world");
array.add("java");
//遍历
Iterator<String> it = array.iterator();
while(it.hasNext())
{
//因为已经定义了集合中元素类型,所以不需要强制转换了
String s = it.next();
System.out.println(s);
}
for(int x=0;x<array.size();x++)
{
String s = array.get(x);
System.out.println(s);
}
}
3.泛型类:
把泛型定义在类上
- 首先不加泛型的类出现的问题:
public class ObjectTool
{
private Object obj;
public Object getObj()
{
return obj;
}
public void setObj(Object obj)
{
this.obj = obj;
}
}
public class ObjectToolDemo
{
public static void main(String[] args)
{
ObjectTool ot = new ObjectTool();
ot.setObj(new Integer(27));
Integer i = (Integer)ot.getObj();
System.out.println("年龄:"+i);
ot.setObj(new String("林青霞"));
String s = (String)ot.getObj();
System.out.println("姓名:"+s);
//报错ClassCastException
ot.setObj(new Integer(30));
String ss = (String)ot.getObj();
System.out.println("姓名:"+ss);
}
}
可以看到集合中的对象元素默认都是以Object类型来存储的,向上转型没有问题,可以向下转型时就隐含了类型转化的问题。
- 加入泛型以后的类:
public class ObjectTool<T>
{
private T obj;
public T getObj()
{
return obj;
}
public void setObj(T obj)
{
this.obj = obj;
}
}
public class ObjectToolDemo
{
public static void main(String[] args)
{
ObjectTool<String> ot = new ObjectTool<String>();
ot.setObj(new String("kk"));
String s = ot.getObj();
System.out.println("姓名:"+s);
ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
ot2.setObj(new Integer(30));
Integer i = ot2.getObj();
System.out.println("年龄:"+i);
ObjectTool<String> ot1 = new ObjectTool<String>();
ot1.setObj(new String("kk"));
//下面报错,试图将String类型转化为Integer对象
Integer i = (Integer)ot1.getObj();
}
}
由此可见,引入泛型以后提高程序的安全性。
4.泛型方法:
把泛型定义在方法上,可以接受任意类型的数据
public class ObjectTool
{
public<T> void show(T t)
{
System.out.println(t);
}
}
public class ObjectToolDemo
{
public static void main(String[] args)
{ /*
//方法的类型和类上的类型相同
ObjectTool<String> ot1 = new ObjectTool<String>();
ot1.show("hello");
ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
ot2.show(10);
ObjectTool<Boolean> ot3 = new ObjectTool<Boolean>();
ot3.show(true);
*/
//方法的类型和类上的类型不一定相同,把类上的类型去掉,定义在方法上
//泛型方法
ObjectTool ot = new ObjectTool();
ot.show("String");
ot.show(100);
ot.show(true);
}
}
5.泛型接口
把泛型定义在接口上
public interface Inter<T>
{
public abstract void show(T t);
}
* 实现类在实现接口的时候有两种情况:
* A:已经知道实现的接口是什么类型了
* B:不知道实现的接口是什么类型
//A:已经知道实现的接口是什么类型了
/*
public class InterImpl implements Inter<String>
{
public void show(String t )
{
System.out.println(t);
}
}
*/
//B:不知道实现的接口是什么类型
public class InterImpl<T> implements Inter<T>
{
@Override
public void show(T t)
{
System.out.println(t);
}
}
public class InterDemo
{
public static void main(String[] args)
{
//A情况测试
Inter<String> i = new InterImpl();
i.show("hello");
//B情况的测试
Inter<String> i = new InterImpl<String>();
i.show("hello");
Inter<Integer> ii = new InterImpl<Integer>();
ii.show(100);
}
}
6.泛型通配符:
- ?:任意的类型都可以
- ? extends E:向下限定,E及其子类
- ? super E:向上限定,E及其父类
public class GenericDemo
{
public static void main(String[] args)
{
//泛型如果明确的时候,前后必须一致
Collection<Object> c = new ArrayList<Object>();
//Collection<Object> c1 = new ArrayList<Animal>();
//Collection<Object> c2 = new ArrayList<Cat>();
//Collection<Object> c3 = new ArrayList<Dog>();
//?表示任意的类型都可以
Collection<?> c5 = new ArrayList<Object>();
Collection<?> c6 = new ArrayList<Animal>();
Collection<?> c7 = new ArrayList<Dog>();
Collection<?> c8 = new ArrayList<Cat>();
//? exends E:向下限定E及其子类
//Collection<? extends Animal> c9 = new ArrayList<Object>();
Collection<? extends Animal> c10 = new ArrayList<Animal>();
Collection<? extends Animal> c11 = new ArrayList<Dog>();
Collection<? extends Animal> c12 = new ArrayList<Cat>();
//? super E:向上限定,E及其父类
Collection<? super Animal> c13 = new ArrayList<Object>();
Collection<? super Animal> c14 = new ArrayList<Animal>();
//Collection<? super Animal> c15 = new ArrayList<Dog>();
//Collection<? super Animal> c16 = new ArrayList<Cat>();
}
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
}