Day16.01_____ArrayList类
- ArrayList中遍历集合的方式
- 通过size()方法和get(int index)方法
- 通过迭代器Iterator中的hasNext()和next()方法
- ArrayList类的特点
- 查询快,增删慢
- 线程不安全,相比Vector效率高
- ArrayList类的运用
- 遍历对象,并获取对应对象中的某些属性
- 删除集合中重复的字符串
// 实现删除重复字符串方法 private static void demo2() { ArrayList list = new ArrayList(); list.add("a"); list.add("a"); list.add("b"); list.add("b"); list.add("c"); list.add("c"); System.out.println(list.toString()); System.out.println(getSingle(list));; } public static ArrayList getSingle(ArrayList list) { ArrayList newList = new ArrayList(); for(int i = 0 ; i < list.size() ; i++) { String temp = (String)list.get(i); if(!newList.contains(temp)) { newList.add(temp); } } return newList; }
- 删除集合中重复的对象
// Person类实现 public class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
// 实现删除重复对象方法 private static void demo3() { ArrayList list = new ArrayList(); list.add(new Person("张三",23)); list.add(new Person("张三",23)); list.add(new Person("李四",24)); list.add(new Person("李四",24)); System.out.println(list); System.out.println(getSingel(list)); } public static ArrayList getSingel(ArrayList list) { ArrayList newList = new ArrayList(); Iterator it = list.iterator(); while(it.hasNext()) { Person p = (Person)it.next(); if(!newList.contains(p)) { newList.add(p); } } return newList; }
- 现象:运行代码我们会发现集合并没有发生变化
- 原因:通过查看contains方法的底层实现,我们发现contains方法底层是依赖于Object类的equals方法的,而Object类中的equals方法比较引用对象时,比较的是对象的地址值,因此!newList.contains§会一直满足,那么解决这个问题,我们的办法是重写equals方法,那么在哪里重写呢?因为Person类默认是继承Object类的,因此我们只需要在Person类中去重写Object类就可以了,修改如下:
public class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } @Override public boolean equals(Object obj) { Person p = (Person)obj; return this.name.equals(p.name) & this.age == p.age; } }
- 集合中除了contatins方法底层是依赖equals方法外,还有remove方法也是依赖于equals方法的,因此如果遇见无法删除的情况,重写equals方法即可解决
Day16.02_____Vector类(了解)
- 因为Vector类出现的比较早,在JDK1.0的时候就出现了,因此最开始没有List的时候,Vector是没有add这些方法的
- 成员方法
- addElement(Object obj)
添加对象 - elementAt(int index)
根据索引查询对象
- addElement(Object obj)
- Vector特点:
- 查询慢,增删快
- 线性安全,相比于ArrayList效率慢
Day16.03_____LinkedList类
- LinkedList特有的功能
- addFirst(Object o)
返回值类型void,用于在链表的首位添加数据 - addLast(Object o)
返回值类型void,用于在链表的末尾添加数据 - getFirst()
返回值类型Object,用于获取集合的第一个对象 - getLast()
返回值类型Object,用于获取集合的最后一个对象 - removeFirst()
返回值类型Object,用于移除集合中的第一个对象,并将该对象返回 - removeLast()
返回值类型Object,用于移除集合中的最后一个对象,并将该对象返回
- addFirst(Object o)
Day16.04_____泛型的基本概念
- 泛型的表示(通过<>进行表示)
例子:ArrayList类的泛型表示(其余接口类的泛型表示也是一样的)
在JDK1.7版本以后泛型可以这么写:ArrayList<Person> list = new ArrayList<Person>(); list.add(new Person("张三",23)); list.add(new Person("李四",24)); Iterator<Person> it = list.iterator(); while(it.hasNext()) { Person p = it.next(); //不用在强制转换 System.out.println(p); }
ArrayList<Person> list = new ArrayList<>(); - 泛型的类型
在<>中只能是引用数据类型,如果想要传入基本类型数据,里面必须使用基本数据类型对应的包装类 - 泛型解决的问题
我们没有规定泛型的时候,通常<>中的Object类型的,因为Object类是所有类的根类,可以接收所有的子类(通过父类引用指向子类对象),但正因为如此会出现以下问题,如代码:
以上代码在编译的时候不会报错,但是在运行的时候会报错,原因在于我们用add方法的时候不仅添加了int类型的数据,还添加了String类型的数据,但是我们在遍历的时候,把int类型和String类型的数据都强转成了Person类型的数据,这样肯定会报错,而报的错就是java.lang.ClassCastException ----> 类转换异常,为了解决这样的问题,在JDK1.5的时候引入了泛型这样的概念ArrayList list = new ArrayList(); list.add(123); list.add("abc"); list.add(new Person("张三",23)); Iterator it = list.iterator(); while(it.hasNext()) { Person p = (Person)it.next(); System.out.println(p.getName() + p.getAge()); }
- 泛型的意义
将运行出现的问题转换成编译的问题 - 泛型什么时候创建
泛型在创建对象的时候创建 - 泛型的好处
- 在遍历的时候,获取对象时不用在强转
- 解决了类转换异常
- 定义泛型的注意事项
- 在我们遍历集合的时候,Iterator的泛型类型必须和集合的泛型类型相同
- 泛型的应用
- 当我们想要将遍历集合的方法抽取出来提供给每个类用时,我们就可以运用到泛型
public static<T> void print(ArrayList<T> list) { Iterator<T> it = list.iterator(); while(it.hasNext()) { T t = it.next(); System.out.println(t); } }
- 当我们想要将遍历集合的方法抽取出来提供给每个类用时,我们就可以运用到泛型
Day16.05_____泛型类
-
泛型类的定义
public class Demo<T>{ private T t; public void set(T t){ this.t = t; } public T get(){ return t; } }
-
泛型方法的定义
public class Demo<T>{ private T t; public void set(T t){ this.t = t; } public T get(){ return t; } public void method(T t){ System.out.print(t); } }
-
泛型类中静态方法的定义
public class Demo<T>{ private T t; public void set(T t){ this.t = t; } public T get(){ return t; } public void method(T t){ System.out.print(t); } public static<M> void print(M m){ System.out.print(m); } }
注意:因为静态的方法是随着类的加载而加载的,而泛型是在创建对象的时候产生的,那么在泛型类中如果要定义静态方法,必须给静态方法重新设置一个泛型,让使用端在调用这个方法的时候对其重新赋值泛型。还需要注意的是即便static与类中的泛型类型相同,但两个仍然属于两个泛型,总结一句话就是,静态方法的泛型是你在调用的时候传入的泛型,传入的是什么就是什么,和类的泛型无关
Day16.06_____泛型接口
- 泛型接口的定义
interface Inter<T>{ public void method(T t); } class Demo implements Inter<String>{ public void method(String t){ System.out.println("hello"); } }
- 泛型接口中泛型在什么时候指定?
当类实现接口的时候,就会确定泛型的类型
Day16.07_____泛型高级之通配符
- 泛型通配符表示
通过?来表示 - ?extends E含义
表示?继承于E - ?extends E的用处:
当我们为一个集合指定了泛型后,整个泛型只能添加指定类型的泛型,但是如果我们在泛型中使用ArrayList<? extends Person>时,这个集合中不仅可以接收Person类型的数据,还可以接收Person子类的数据。其中E是,这种类型也叫固定上边界
Day16.08_____增强for循环—>foreach
-
foreach格式
- 集合的遍历
这里的容器名指的是,定义集合的变量名;for(泛型类型 临时变量名:容器名){ 语句; }
如果没有泛型类型,默认为Object类型 - 数组的遍历
这里的容器名指的是,定义数组的变量名字for(数组类型 临时变量名:容器名){ 语句; }
- 集合的遍历
-
foreach例子
ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); for (String string : list) { System.out.println(string); }
-
foreach与Iterator的区别
- foreach既可以遍历数组又可以遍历集合,而Iterator只能遍历集合
- foreach书写简洁,Iterator书写复杂
Day16.09_____可变参数
- 什么是可变参数
可变参数其实就是一个长度可以变化的数组 - 可变参数的定义
public void method(int … arr){} - 例子
可变参数的取值范围为0—正无穷public static void main(String[] args) { method(11,22,33,44,55); } public static void method(int ... arr) { for (int i : arr) { System.out.println(i); } }
传入参数的时候,必须与可变参数的参数类型一致 - 注意事项
当我们使用了可变参数以后,可变参数后面不能再定义其他参数,因为后面的这个参数永远也没有办法获取到。但是在可变参数的前面我们可以定义其他参数
public static void method(int … arr,int a) ----> 这样是错误的
public static void method(int a,int … arr) ----> 这样是可以的
Day16.10_____JDK1.5特性
- 自动拆装箱
- 泛型
- for增强循环
- 静态导入( 静态导入导入的其实是方法 )
- 可变参数