集合的诞生
为什么学习集合?
集合就是容器
容器有 数组 StringBuffer StringBuider
数组的局限性:
1.只能够存储一组相同数据类型的容器
2.数组中只有length属性,没有供我们操作对象的方法 Book[] int[]
StringBuffer StringBuider特点:
1.只能够存储字符串类型
2.有对字符串进行增加删除修改的方法
集合应该具备以下功能:
- 1.作为容器存在
- 2.集合既只能够存储引用数据类型,但是集合可以存储基本数据类型对应包装类类型,强制我们使用包装类
- 3.集合同时也可以对集合中的元素进行随意增加删除修改查询
- 4.集合是可以动态扩容,缩容
数组和集合的区别:
- 长度
数组的长度固定不变的
集合长度是可以根据实际需要改变 - 内容
数组存储的是同一种类型的元素
集合可以存储不同类型的元素 - 数据类型
数组可以存储基本数据类型,也可以存储引用数据类型
集合只能存储引用类型
注意:虽然集合不能存储基本数据类型,但是可以存储基本数据类型的包装类类型
集合的概述: 集合是一套容器框架
-
为什么集合是一套框架?
**容器中的元素可能是有序的,无序,可排序,重复的,唯一的,线程安全的,线程不安全等等特点. ** -
既然是框架,肯定有框架体系图,顶层父类设计为接口还是设计成类?
(为什么集合要是一个接口)
假设为抽象类,定义属性不方便:你可能要定义:元素的重复属性,排序属性,唯一属性,线程安全属性,先不谈有的类不需要这些属性,比方说你要存放身份证和年龄,这种特定的属性定义类不合适,如果用接口可以很方便的做到身份证用String、不重复,年龄用int 可以重复。
集合顶层父类应该设计为接口 这个接口叫做 Collection【单列集合】 和 Map【双列集合】
Collection的方法
增加
boolean add(Object e)
boolean addAll(Collection c)
Collection c=new ArrayList();
Staff s1=new Staff("001","madaha");
Staff s2=new Staff("002","幼儿园");
c.add(s1);// -------------------------添加方法1
c.add(s2);
Collection c2=new ArrayList();
c2.add("xcv");
c2.add("acs");
c.addAll(c2);//-------------------------添加方法2
删除
void clear()
boolean remove(Object o)
boolean removeAll(Collection c)
System.out.println(c.removeAll(c2)); //删除集合
System.out.println(c.remove(s1)); //删除对象
修改
查询(遍历)
Object[] toArray()
T[] toArray(T[] a) 泛型
Iterator iterator() 迭代器
interface Collection extends Iterable {
Iterator<T> iterator();
}
interface Iterable {
Iterator<T> iterator();
}
public interface Iterator<E> {
boolean hasNext();// 放在while for中
Object next(); //获取对象
}
案例分析:(把前三个遍历吃透,用的很多)
Collection<String> c=new ArrayList();
c.add("asd");
c.add("zxc");
c.add("qwe");
//用toArray的泛型方法(不用强转!)
String[] ars = c.toArray(new String[]{});
for (String o : ars) {
System.out.println(o);
}
//用foreach遍历(本质也是迭代器,只不过把迭代器写在了for里)
for(Object o:c){
String s=(String)o;
System.out.println(s);
}
//用迭代器进行遍历
Iterator is=c.iterator();
while(is.hasNext()){
String s=(String)is.next();
System.out.println(s);
}
//用集合的toArray获取对象,进行遍历
Object []os=c.toArray();
for(int i=0;i<c.size();i++){
String s=(String)os[i];
System.out.println(s);
}
//for循环进行遍历
for(;is.hasNext();){
String s=(String) is.next();
System.out.println();
}
- 判断
boolean contains(Object o) //集合是否包含o对象
boolean containsAll(Collection c)
boolean isEmpty() //集合为空否(为空时true)
System.out.println(c.contains("oi"));
System.out.println(c.containsAll(c2));
- 获取
int size() - 其他
boolean retainAll(Collection<?> c) 求两个集合的交集,返回原集合是否发生改变,发生了改变返回true,否则返回false
System.out.println(c.retainAll(c3));//c1与c3取交集,返回true
//c1:[as, zx, av, ds] c3:[oi, av, zx]
//c.retainAll(c3) 取交集将结果给c c:[zx, av]
Iteroator原理
源码遍历集合的方式:
hasNext方法:
public boolean hasNext() {
return cursor != size;
}
next方法:
public E next() {
checkForComodification();
int i = cursor;//初始指向第一个,一般为0
if (i >= size)//空间大小比较
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)//实际长度比较,cursor在其他地方也会调用 比如集合修改会动cursor
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];//返回第i个
}
数组toString的方法:(它不会一直死循环-----------------有return)
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext()) //刚好cursor = size;
return sb.append(']').toString();
sb.append(',').append(' ');
}
}