1. 泛型接口的使用
public static void main (String[] args){
//泛型接口
//格式: public interface 接口名<泛型类型>
}
//定义个接口
public interface inter<T>{
//定义个方法
public void show(T t);
}
//有个类实现了这个接口
//第一种方式--指定具体的泛型类型(推荐用这种)
public class Demo implements inter<String>{
public void show(String t){
System.out.println(t);
}
}
//第二种方式--并不指定具体的泛型类型--没有必要在实现接口的时候给自己类加泛型
// class Demo1<T> implements inter<T>{
// public void show(T t){
// System.out.println(t);
// }
// }
2. 泛型高级之通配符
List<?>list = new ArrayList<String>();
//在我们有时创建集合的时候,并不一定知道我们接收的是什么类型的元素
//我们就可以用通配符,说明我们的集合可以接收任何类型数据
//所以当右边是不确定泛型的时候,左边可以用通配符
//注意左边不是用Object匹配的--这样左右泛型是不一致的
3. 增强for循环—底层依赖的是迭代器
//增强for循环遍历--和iOS中的for(in)遍历效果一样
int[] arr = {11,4,444,55,55,66,65,32};
//快捷键:fore
for (int i : arr){
System.out.println(i);
}
System.out.println("-------------------");
String[] arr1 = {"dd","我是shei","帅哥","美女","老司机"};
for (String str : arr1){
System.out.println(str);
}
4.
//三种遍历方法可否删除
/*
* 1.普通for循环:可以删除
* 2.迭代器:可以删除,但是必须使用迭代器自身的remove方法,否则会有并发修改错误
* 3.增强for循环--不能删除
* */
//1.普通for循环
ArrayList<String> list = new ArrayList();
list.add("qq");
list.add("jj");
list.add("jj");
list.add("jj");
list.add("pp");
list.add("uu");
for (int i = 0; i < list.size(); i++){
if ("jj".equals(list.get(i))) {
//list.remove(i);//普通for循环可以直接删除
//看了这个普通for循环进行删除的原理后,你就会明白如果我们的数据是挨着的,那么会出现漏删的情况
//这是因为当我们执行一次remove操作后,在ArrayList集合中的元素会整体向上移动,而i作为索引是加1的
//这样的话,如果我们删除中的有紧挨着的重复元素,就会出现漏删
//解决办法是,在删除完成后,将i的索引回退一位
list.remove(i--);
}
}
System.out.println(list);
System.out.println("1---------------------");
//2.迭代器遍历
list.add("89");
ListIterator it = list.listIterator();
while (it.hasNext()){
if ("uu".equals(it.next())){
it.remove();
}
}
System.out.println(list);
System.out.println("2-----------------------");
//3.增强for循环
list.add("tmac");
for (String str : list) {
if ("tamc".equals(str)){
list.remove("tamc");//增强for循环底层依赖的是迭代器,所以是无法删除的,会引起并发修改异常
}
}
System.out.println(list);
5. 可变参数方法
//可变参数
int[] arr = {11,44,43,23,54,65};
//使用可变参数方法:
print(22,33,44,55);//这就是使用可变参数方法的强大之处
System.out.println("-------------------------");
print();//对于可变参数,可以传入的元素个数是0到无穷大
}
//正常方法我们传一个数组
// public static void print(int[] arr){
// for (int i : arr){
// System.out.println(i);
// }
// }
//可变参数方法(我们如果不注释上面的方法,我们写上这个可变参数的方法就会报错,说明我们可变参数方法
// 给的参数和上面的参数是一样的。 事实也是这样的:就是这个int...就相当于int数组,前面是什么类型,就是什么数组)
public static void print(int...arr){
for (Object ob : arr){
System.out.println(ob);
}
}
6. 集合转数组,数组转集合
//asList工具的使用
//1.数组转集合--虽然不能增加和减少,但是可以用集合中的其它方法,集合的方法比数组丰富很多
String[] arrs = {"tmac","kobe","jj","sout","souf"};
List<String> list = Arrays.asList(arrs);
System.out.println(list);
System.out.println("1---------------------------");
//数组转集合的好处--以为可以增加元素等操作,结果不行
// list.add("jjtmac");
// System.out.println(list);
//报错:java.lang.UnsupportedOperationException不支持更改异常
//2.再来个int类型的数组,转为集合
int[] arrI = {12,44,53,68,35,89,3};
List list1 = Arrays.asList(arrI);
//List<int> list2 = Arrays.asList(arrI);//这里我们给集合加个int的泛型是不行的,因为这里的泛型类型是int[]
System.out.println(list1);
//这里打印出来是一个地址值,是因为这里是将int[]整个数组作为一个元素加入到集合中
//对于基本数据类型数组转为集合会被弄成一个对象,必须是引用数据类型的
Integer[] ite = {11,44,664,664,2222,22};
List<Integer> list2 = Arrays.asList(ite);
System.out.println(list2);
System.out.println("2------------------");
//3.集合转数组
ArrayList<String> list3 = new ArrayList();
list3.add("a");
list3.add("b");
list3.add("c");
list3.add("d");
//这个方法里要求我们传入一个String[] 的对象
String[] strarr = list3.toArray(new String[0]);
//这里我们给String[0]:传入的长度小于等于集合的size就好,超过的话,多余的位置就是null
for (String str : strarr){
System.out.println(str);
}
7. ArrayList嵌套ArrayList
//ArrayList嵌套ArrayList
//集合中放集合
ArrayList<ArrayList<Student>> list = new ArrayList<>();//放有班级的大集合
ArrayList<Student> firstList = new ArrayList<>();//创建第一个由学生组成的班级
//给第一个班级添加人
firstList.add(new Student("tamc",19));
firstList.add(new Student("jj",34));
firstList.add(new Student("jkkj",98));
firstList.add(new Student("jsh",87));
ArrayList<Student> secondList = new ArrayList<>();//创建第二个由学生组成的班级
//给第二个班级添加人
secondList.add(new Student("kobe",19));
secondList.add(new Student("linek",34));
secondList.add(new Student("huohude",98));
secondList.add(new Student("love",87));
//我们大集合添加每个班级集合
list.add(firstList);
list.add(secondList);
//遍历--循环嵌套循环遍历
for (ArrayList<Student> listS : list){
for (Student s : listS){
System.out.println(s);
}
}
8. Set集合子类学习
//HashSet学习--Set集合没有索引,不可以存储重复值,存取无序
HashSet<String> hs = new HashSet<>();
boolean b1 = hs.add("a");
boolean b2 = hs.add("a");//因为Set集合不能存储重复元素,所以b2返回应该为false
hs.add("b");
hs.add("c");
hs.add("d");
System.out.println(hs);
//用增强for循环遍历
for (String str : hs){//只要能用迭代器遍历的,都可以用增强for循环
System.out.println(str);
}
//方法都和List一模一样的
9. 用Set存储自定义对象,看其如何保证元素唯一性
//用存储自定义对象验证HashSet如何保证元素唯一
HashSet<Student> hs = new HashSet<>();
hs.add(new Student("tmac",34));
hs.add(new Student("jjjj",34));
hs.add(new Student("kobe",78));
hs.add(new Student("jing",76));
hs.add(new Student("kine",34));
hs.add(new Student("kine",34));
hs.add(new Student("kine",34));
hs.add(new Student("kine",34));
//我们添加了几个感觉是重复的学生对象
//打印hs的size,我们发现为7,说明这个所有都存进来了,
System.out.println(hs.size());
System.out.println(hs);
//接下来给你解释这个存储原理
/*
* 我们举例,想hs中存入一个Student对象,就像我们上火车一样。
* 我们都要找个位置坐,第一个上来的tmac找个位置坐,它的位置号码是根据其地址值算出的hashCode决定的
*然后其它人依次上了,到kine,我们添加了很多个重复的kine。但是他们的hashCode都是不一样的。所以,HashSet认为
* 他们都是不一样的东西,就不会认作是重复值
* 我们在Student类中作一个操作:重写其hashCode方法,统一返回一个数。
*这个效果就好比,大家的火车座位号都是一样的。那么我们就只能根据表面现象,看看哪些是不一样的对象
*然后我们也重写了Student类的equals方法,只比较对象的字面值
* */
@Override
public boolean equals(Object obj){
System.out.println("equals调用了");
//比较字面值,不比较地址
Student s = (Student)obj;
if (this.name.equals(s.name) && this.age == s.age){
return true;
}else{
return false;
}
}
@Override
public int hashCode() {
//return 100;
return this.name.hashCode() + this.age;
}
//针对这个hashCode的返回值,如果我们都返回一样的,那我们无论加什么对象,
//都会去调用一下equals方法。这样不是很好,如果我们返回属性值,那么就相当于
//先比较一次属性值,那么就会少调用几次equals方法了
10. LinkedHashSet概述和使用
//LinkedHashSet的使用:底层是链表实现的,是set中唯一一个怎么存怎么取的
//由于又是HashSet的子类,所以也可以保证元素唯一
LinkedHashSet<String> lin = new LinkedHashSet<>();
lin.add("a");
lin.add("b");
lin.add("c");
lin.add("d");
lin.add("c");
lin.add("a");
System.out.println(lin);