泛型
数组直接定义了存储的类型,防止出现其他类型的元素,集合能不能也像数组一样,直接规定我们集合的存储类型,针对这种情况
引进一种技术:泛型
<数据类型> --- 引用数据类型
泛型:将明确的集合类型的工作推迟到了创建对象或者调用方法的时候,属于一种参数化类型,可以作为参数传递.
泛型的好处:
1)将运行时期异常提前到了编译时期
2)优化了设计,解决了黄色警告线问题
3)避免了强制类型转换
为什么引出泛型?
1. 泛型的引出可以提供程序的安全性!
解决了java.lang.ClassCastException:类转换异常
2.在早期的时候,使用Object类型代表任意类型,向上转型没有问题,
使用向下转型的时候,可能会出现问题(需要的类型有问题),这个时候就需要引入泛型操作
在API文档上,接口,类,方法上有<E> ,都是泛型
public class ObjectTool<T> {
//将泛型定义在接口上
public interface Inter<T> {
//接口中变量是常量: public static final int num ;
public abstract void show() ; //抽象方法
//泛型的应用:在接口中,类中,方法上应用,在集合中应用最多!
//接口中泛型,子实现类的第一种情况,就是已经知道是什么类型了
//第二种情况,就是不知道具体的类型是什么
泛型高级(通配符)
<?> :代表任意类型Object类型,或者任意的Java类
<? extends E>:向下限定,E的子类或者E这个类型
<? super E>:向上限定,E及其他的父类
ArrayList集合
ArrayList是List接口中常用的一个子实现类
遍历功能:
1)一个是Collection的iterator()
2)size()和get(int index)普通for循环
public class ArrayListDemo1 {
public static void main(String[] args) {
ArrayList<String> l=new ArrayList();
l.add("hello");
l.add("world");
l.add("java");
Iterator<String> it=l.iterator();
while(it.hasNext()) {
String s=it.next();
System.out.println(s);
}
}
}
Vector集合
Vector集合的特点:
底层是一种可增长对象数组,查询快,增删慢
线程安全,同步,执行效率高
特有功能:
public void addElement(Object obj)------->add(Object obj)
public Enumeration elements():返回此向量的枚举--->相当于:public Iterator iterator()
boolean hasMoreElements() --->boolean hasNext() ;
Object nextElement() --->Object next() ;
import java.util.Enumeration;
import java.util.Vector;
public class VectorDemo1 {
public static void main(String[] args) {
Vector v=new Vector() ;
v.addElement("hello");
v.addElement("world");
v.add("javaee");
Enumeration<String> e=v.elements();
while(e.hasMoreElements()) {
String s=e.nextElement();
System.out.println(s);
}
}
}
LinkedList集合
LinkedList集合的特点:
底层是一种链表实现,查询慢,增删快
线程不安全的,不同步,执行效率高
特有功能:
添加功能
addFirst(Object e):将指定的元素插入到列表的开头
addLast(object e):将指定的元素添加到列表末尾
获取功能:
getFirst():获取列表第一个元素
getLast():获取列表第二个元素
删除功能
public Object removeFirst()移除并返回此列表的第一个元素。
public Object removeLast()
模拟栈结构的特点,先进后出
import java.util.Iterator;
import java.util.LinkedList;
class Mystack{
private LinkedList list;
public Mystack() {
list=new LinkedList<>();
}
public void add(Object obj) {
list.addFirst(obj);
}
public Object get() {
return list.removeFirst();
}
public boolean isEmpty() {
return list.isEmpty();
}
}
public class MystackDemo1 {
public static void main(String[] args) {
Mystack m=new Mystack();
m.add("hello");
m.add("world");
m.add("java");
while(!m.isEmpty()) {
System.out.println(m.get());
}
}
}
需求:给集合中添加重复的元素(字符串类型),将重复的元素从集合去除掉!
思路:
1)创建一个旧集合,添加重复元素
2)创建一个新集合
3)遍历旧集合中的元素获取到每一个元素
在旧集合中判断新集合中是否包含旧集合中的元素
包含,不搭理
不包含,添加到新集合中
4)遍历新集合
import java.util.ArrayList;
import java.util.Iterator;
//去重集合中重复的元素
//假设:现在的需求:不允许新建一个集合去完成,怎么办?
public class ArrayListTest2 {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList array = new ArrayList() ;
//添加元素
array.add("hello") ;
array.add("world") ;
array.add("java") ;
array.add("javaee") ;
array.add("hello") ;
array.add("world") ;
array.add("hello") ;
array.add("javaee") ;
//System.out.println(array);
//引入选择排序,
//用0索引对应的元素依次和后面索引对应的元素进行比较
//如果前面的元素和后面的元素重复了,把后面元的干掉
// 依次1索引....
for(int x = 0 ; x < array.size()-1 ; x ++) {
for(int y = x +1 ; y < array.size() ; y ++) {
//判断,前面的索引对应的元素和后面索引对应的元素进行比较,如果相等就干掉后面重复的
if(array.get(x).equals(array.get(y))) {
array.remove(y) ;
y-- ;
}
}
}
//遍历集合
Iterator it = array.iterator() ;
while(it.hasNext()) {
String s = (String) it.next() ;
System.out.println(s);
}
}
}
需求:使用集合ArrayList存储自定义对象(Student),去除重复的对象(成员变量的值一样,看成一个人)
问题:按照存储字符串(新建集合的思想)的形式来去存储自定义对象,发现自定义对象并没有去重,为什么?
因为contains方法底层依赖于equals方法
equals方法默认比较的是地址值,如果想让equals()方法比较他们的内容是否相同,需要重写equals(),也就意味着存储自定义类必须重写equals()方法,这样才能比较的是这些对象的内容是否相同
可变参数
可变参数:当一个方法的参数个数不确定的时候,要使用可变参数
格式: 修饰符 返回值类型 方法名(数据类型...变量名){...}
注意:
1)变量名:看成一个数组
2)使用的时候数据类型 ...
注意:根据具体的需求去完成,一般情况,知道有这个特性就可以了
增强for循环
ArrayList集合存储自定义对象并遍历,有几种方式?
1.Iterator iterator() ;
2.listIterator listiterator();(可以不写)
3.普通for循环:size()/get(int index)
4.增强for循环
public class 增强for {
public static void main(String[] args) {
String [] str= {"hello","world","java"};
for(String s:str) {
System.out.print(s+" ");
}
}
}
asList方法
针对数组操作的工具类:Arrays,提供了一个方法:
public static <T> List<T> asList(T... a) :将数组转换成固定大小的集合
注意:如果使用此方法,那么集合的长度不可变
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class AsListDemo1 {
public static void main(String[] args) {
String[] s= {"hello","world","javaee"};
List<String> l=Arrays.asList(s);
Iterator<String> it=l.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
Jdk5以后的新特性
增强for,静态导入,可变参数,泛型,自动拆装箱...
增强for循环的格式
for(数据大类型 变量名 : 数组或者集合对象名){
输出变量即可!
}
增强for的出现时替代迭代器的,所以在遍历集合或者遍历数组就可以使用增强for去完成
增强for循环的弊端:如果集合的对象是null,如果再次对集合操作,就会出现异常
解决办法:对集合进行判断
静态导入:Jdk5一个新特性
特点:
1)前提是该方法必须是静态的
2)导入到的一个方法的级别
静态导入的格式:
import static 包名.类名.方法名;
错误:import static java.util.ArrayList.add; 方法必须是静态方法
之前导包:java.util.Scanner; 导入到类的级别
import static java.lang.Math.abs; 导入到方法的级别
集合的嵌套遍历
有一个Java基础班,里面有很多学生,把一个班级集合:ArrayList<Student>
不止一个Java基础班,这个时候就定义大集合:ArrayList<ArrayList<Student>>
有三个基础班,分别遍历每一个班里面学生信息:(name,age)
步骤:
第一步:将每个班的学生先添加到小集合
第二部:将每个小集合添加到大集合
遍历:
采用增强for嵌套遍历
集合接收随机数:
需求: 求10个1~20之间的随机数,要求数据不能重复
分析:
可以使用数组,数组的长度固定,不够好,使用集合去做
创建一个随机数类对象
Random
获取指定的随机数的范围:
int nextInt() ; 获取的int类型的范围
int nextInt(int n) ;获取1~n之间的数据 ,[0,n)
创建一个ArrayList集合对象,元素类型:Integer类型
定义统计遍历:count 是从0开始
判断如果统计遍历小于10
先计算出1-20之间的随机数,还需要判断集合中是否包含这些元素
如果不包含,添加,count++
包含,重复,不搭理了....
大于10,不搭理
遍历即可
import java.util.ArrayList; import java.util.Random; public class 集合添加随机数 { public static void main(String[] args) { Random r=new Random(); ArrayList<Integer> l=new ArrayList(); int n=0; while(n<10) { int num=r.nextInt(20)+1; if(!l.contains(null)) { l.add(num); n++; } } for(int i:l) { System.out.println(i); } } }