1.集合和数组既然都是容器,它们有什么区别呢?
1.集合和数组都是容器,可以存储多个数据
2.数组的长度是固定的。集合的长度是可变的。
3.数组中存储的是同一类型的元素,可以存储任意类型数据。
集合存储的都是引用数据类型。如果想存储基本类型数据需要存储对应的包装类型。
-
java.util.Collection接口:
单列集合的根接口,里面定义的方法,实现类/子接口中都有常用的子接口:
1.List子接口
(1)有序(保证存入和取出元素的顺序是一致的)
(2)有索引
(3)可重复
2.Set子接口
(1)无序(不保证存入和取出元素的顺序是一致的)
(2)没有索引
(3)不可重复常用方法:
- public boolean add(E e): 把给定的对象添加到当前集合中 。
- public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。
- public boolean isEmpty(): 判断当前集合是否为空。
- public int size(): 返回集合中元素的个数。
- public boolean remove(E e): 把给定的对象在当前集合中删除。
- public Object[] toArray(): 把集合中的元素,存储到数组中
- public void clear() :清空集合中所有的元素。
-
并不是所有的集合都有索引
那么,以前通过for使用索引的形式遍历集合元素,就不通用了
jdk提供了一个工具: Iterator接口
是一种遍历集合的通用的方式java.util.Iterator接口
抽象方法:
public boolean hasNext(): 判断是否具有下一个元素,有: true 没有: false
public E next(): 获取下一个元素
public void remove(): 删除当前元素java.util.Collection接口
抽象方法:
Iterator iterator(): 获取迭代器Iterator接口的实现类对象子接口List
java.util.List extends Collection List子接口继承父接口Collection Collection中定义的方法List中有
相当于List子接口中也有一个抽象方法:
Iterator iterator(): 获取迭代器Iterator接口的实现类对象我们使用的是实现类,比如: ArrayList
ArrayList是List接口的实现类,比如覆盖重写List接口中的抽象方法public class ArrayList implements List {
//必须覆盖重写抽象方法iterator
public Iterator iterator() {
//…
return MyItr();
}
//定义了Iterator接口的实现类(内部类)
public class MyItr implements Iterator {
//覆盖重写
public boolean hasNext() {
//…
}
public E next() {
//…
}
public void remove() {
//…
}
}
} -
集合存储int数字并遍历
迭代器的使用步骤:
1.集合对象调用iterator方法,获取迭代器对象
2.迭代器对象调用hasNext方法,判断是否具有下一个元素
3.如果有,迭代器对象调用next方法,获取下一个元素
*/
5.遍历数组的格式:
for(数组中存储的数据的类型 变量名称 : 数组名称){
//…
}
注意:
1.增强for遍历数组,底层使用的是普通for
2.增强for遍历数组, 尽量不要完成对数组元素的增删改的操作
泛型的好处:
1.避免强制类型转换的麻烦
2.将运行时异常,提前到了编译时期,降低了程序员的工作量
3.一旦指定泛型,数据类型将被统一
4.实现代码的模板化,把数据类型当做参数传递
泛型(不确定的/未知的数据类型):
1.可以定义在类上
2.可以定义在方法上
3.可以定义在接口上
-
*/ 泛型类(含有泛型的类)的定义:
格式:
public class 类名<泛型变量> {
//…
}
泛型变量: 一般用大写字母表示,比如: K,V,E,T,A泛型类上的泛型,什么时间确定呢?
创建对象时确定,创建对象时<>写的是什么类型,泛型就代表什么类型
*
定义泛型类
定义类MyClass时,发现该类中要处理某些类型的数据,但是什么类型,
不确定,就用泛型表示
在MyClass类中,可以提前使用这种未知的类型T
*/
public class MyClass<T> {
private T t;
public MyClass() {
}
//构造方法
public MyClass(T t) {
this.t = t;
}
//set get
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
//toString
@Override
public String toString() {
return "MyClass{" +
"t=" + t +
'}';
}
}
8.` 泛型方法(方法上含有方法自己的泛型)
格式:
修饰符 <泛型变量> 返回值类型 方法名称(参数列表...) {
//...
}
泛型方法上定义的泛型,什么时间确定?
调用方法时确定,传递的参数是什么类型,泛型就是什么类型
*/
public class Demo01GenericMethod {
public static void main(String[] args) {
MyClass02<String> mc = new MyClass02<>();
mc.print("Hello");
//mc.print(1000);//错误的,只能传递String类型
//show方法上含有泛型,调用方法时,传递String类型
//方法内部的泛型就是String类型
mc.show("wolrd");
//show方法上含有泛型,调用方法时,传递Integer类型
//方法内部的泛型就是Integer类型
mc.show(2000);
}
}
9.
泛型接口(定义接口上含有泛型)
格式:
public interface 接口名<泛型变量> {
//...
}
接口上定义的泛型,什么时间确定?
1.定义实现类时,直接确定接口上的泛型的具体类型
2.定义实现类时,不确定接口上的泛型的具体类型,
创建实现类对象时,确定接口上的泛型的具体类型,
要求实现类,必然是一个泛型类(泛型传递)
`
10.泛型的注意事项:
1.泛型是不存在多态的: 创建对象时左右两边<>中写的内容必须一致
2.ArrayList<?> list:
可以接收ArrayList集合的任意泛型对象(创建ArrayList集合对象时,只要在<>中写上一种引用类型都是可以的)
泛型通配符:
?: 代表任意的数据类型
注意:
只能用来匹配泛型,不能用来定义泛型
*/
泛型的上限:
父类: Person
子类: Worker
子类: Teacher
子类: JavaTeacher
分析:
一个类的子类,有很多个
如何表示一个类的所有子类呢?
? extends Person: Person的任意子类或者Person类型
? extends E: E的任意子类或者E类型
*/
泛型的下限:
子类: Teacher
父类: Worker
父类: Person
父类: Object
分析:
一个子类的父类,有很多个
如何表示一个子类的所有父类呢?
? super Teacher: Teacher的任意父类或者Teacher类型
? super E: E的任意父类或者E类型