## Collection
- 集合:集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
- 数组的长度是固定的。集合的长度是可变的。
- 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
*集合框架:
集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map,
- Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。
其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,
Set接口的主要实现类有java.util.HashSet和java.util.TreeSet。
*目标:
1.会使用集合存储数据
2.会遍历集合,取数据
3.掌握每种集合的特性
*Collection接口
定义了所有单列集合中共性的方法
所有的单列集合都可以使用共性方法
没有带索引的方法
包含了list与set接口
*list接口:
1.有序的集合(存取元素的顺序相同)就是说存的是123,取还是123.
2.允许存储重复的元素
3.有索引可以使用普通的for循环遍历
包括: Vector ArrayList LinkedList
(基本不用了)
*set接口:
1.不允许存储重复元素
2.没有索引(不能使用普通for循环遍历)
3.无序的集合(存取元素的顺序有可能不一致)
包括TreeSet HashSet
4. LinkedHashSet是有序的集合
*Collection中的常用方法
所有单列集合最顶层的接口,里面定义了所有单列集合共性的方法
public boolean add(E e): 把给定的对象添加到当前集合中 。
public void clear() :清空集合中所有的元素。
public boolean remove(E e): 把给定的对象在当前集合中删除。
public boolean contains(E e): 判断当前集合中是否包含给定的对象。
public boolean isEmpty(): 判断当前集合是否为空。
public int size(): 返回集合中元素的个数。
public Object[] toArray(): 把集合中的元素,存储到数组中。
## Iterator迭代器(遍历单列集合)
*java.util.Iterator,Iterator接口:主要用于迭代访问(遍历)元素,因此Iterator对象也被称为迭代器.
*迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,
如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
*获取迭代器:public Iterator iterator(){}
方法返回的就是迭代器的对象
Iterator it = 对象.iterator();
*迭代器的使用步骤:
1.使用集合中的方法iterator()获取迭代器的实现类对象,并接收
2.使用hasNext()判断
3.使用next()获得
*Iterator接口中的常用方法
*public E next():返回迭代的下一个元素
*public boolean hasNext():如果仍有元素可以迭代,则返回true
*迭代器的代码实现:
public static void main(String[] args){
Collection <String> coll = new ArrayList<>();
coll.add("hello");
coll.add("hello");
coll.add("hello");
coll.add("hello");
coll.add("hello");
//迭代器是有泛型的,集合是什么泛型,迭代器就是什么泛型
Iterator<String> it = coll.iterator;
while(it.hasNext(){
String string = it.next();
System.out.println(string);
}
}
*遍历时候不能增删,否则会报ConcurrentModificationException并发修改异常
一般会另建一个集合,equals拷贝到新集合
*jdk有一个bug:只有删除倒数第二个的时候不会报错
## 增强for循环
*也叫foreach jdk1.5以后,不能增删,只能遍历
*底层使用的也是迭代器,简化了迭代器的书写
*格式:
for(集合/数组的数据类型 变量名:集合名/数组名){
sout(变量名);
}
*增强for循环必须有被遍历的目标,目标只能是Collection或者是数组.只能作为遍历
## 泛型
*是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型
*泛型也可以看做是一个变量用来接收数据类型
E e:Element 元素
T t:type 类型
*一般在创建对象的时候就会确定泛型(会把数类型作为参数传递)
*使用泛型的好处
*创建集合对象,不使用泛型
好处:集合不使用泛型,默认的是Object.可以存储任意的类型
弊端:不安全.会引发异常(在使用子类的方法时候要转型,不安全)
*创建集合对象,使用泛型
好处:1.避免了类型转换的麻烦,存储的什么类型,取出的就是什么类型
2.把运行时期的异常(代码运行之后会抛出的异常),提升到了编译期
弊端:泛型是什么类型,就必须存储什么类型的数据
*定义含有泛型的类
public class 类名<E>{
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
在创建对象时传递泛型的数据类型
*定义含有泛型的方法
修饰符 <泛型> 返回值类型 方法名(参数列表 (使用泛型){
方法体
}
定义静态方法含有泛型
修饰符 static <泛型> 返回值类型 方法名(参数列表 (使用泛型){
方法体
}
*调用含有泛型的方法时候,传递任意类型的参数,传递什么类型的,泛型就是什么类型
public <E> E setName(E e){
sout(e);
return e;
}
*接口带有泛型,就是在接口名后加上泛型.
两个方法:一个是在实现类直接定义好泛型
一个是在实现类也是实现接口的泛型,在实例化时候确定泛型
*泛型通配符:?->代表任意的数据类型
在不知道使用什么类型接受数据时候使用
*使用方式:
不能创建对象使用
只能作为方法的参数使用
泛型没有继承的概念,所以不写object而是使用?
*泛型的上限限定: ? extends E 代表使用的泛型只能是E类型的子类/本身
*泛型的下限限定: ? super E 代表使用的泛型只能是E类型的父类/本身