Java 集合框架 02
集合框架· LinkedList 和 泛型
去除ArrayList中重复字符串元素
* A:案例演示
* 需求:ArrayList去除集合中字符串的重复值(相同内容的字符串)
* 思路:创建新集合方式
package com.heima.list; import java.util.ArrayList; import java.util.Iterator; public class Demo1_ArrayList { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("a"); list.add("a"); list.add("b"); list.add("b"); list.add("b"); list.add("b"); list.add("c"); list.add("d"); ArrayList newList = getSingle(list); System.out.println(newList); } /* * 创建新集合将重复元素去掉 * 1、明确返回值类型:ArrayList * 2、明确参数列表:ArrayList list * * 分析: * 1、创建新的集合 * 2、根据获取的集合(老集合)获取迭代器 * 3、遍历老集合 * 4、通过新集合判断是否包含老集合中的元素,如果包含就不添加,如果不包含就添加 */ public static ArrayList getSingle(ArrayList list) { ArrayList newList = new ArrayList(); // 创建新集合 Iterator it = list.iterator(); // 获取迭代器 while (it.hasNext()) { // 遍历老集合 Object object = (Object) it.next(); // 记录每个元素 if (!newList.contains(object)) { // 如果新集合中不包含老集合中的元素 newList.add(object); // 就将该元素添加到新集合中 } } return newList; // 返回新集合 } }
去除ArrayList中重复自定义对象元素
* A:案例演示:
* 需求:ArrayList去除集合中自定义对象元素的重复值(对象的成员变量值相同)
* B:注意事项
* 重写equals() 方法
@Override public boolean equals(Object obj) { Person person =(Person)obj; return this.name.equals(person.name) && this.age == person.age; }
package com.heima.list; import java.util.ArrayList; import java.util.Iterator; import com.heima.bean.Person; public class Demo2_ArrayList { public static void main(String[] args) { ArrayList list = new ArrayList(); // 创建集合对象 list.add(new Person("张三", 23)); list.add(new Person("张三", 23)); list.add(new Person("李四", 24)); list.add(new Person("李四", 24)); list.add(new Person("李四", 24)); list.add(new Person("李四", 24)); list.add(new Person("李四", 24)); ArrayList newList = getSingle(list); // 调用方法去除重复 System.out.println(newList); // remove() 方法底层依赖的也是equals()方法 list.remove(new Person("张三", 23)); System.out.println(list); } // contains()方法底层依赖equals方法,equals未重写前是判断地址值 public static ArrayList getSingle(ArrayList list) { ArrayList newList = new ArrayList(); // 创建新集合 Iterator it = list.iterator(); // 获取迭代器 while (it.hasNext()) { // 遍历老集合 Object object = (Object) it.next(); // 记录每个元素 if (!newList.contains(object)) { // 如果新集合中不包含老集合中的元素 newList.add(object); // 将该元素添加到新集合中 } } return newList; } }
LinkedList的特有功能
* A:LinkedList类概述
* B:LinkedList类特有功能
public void addFirst(E e) public void addLast(E e) public E getFirst() public E getLast() public E removeFirst() public E removeLast() public E get(int index)
public E get(int index) { checkElementIndex(index); return node(index).item; } Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
package com.heima.list; import java.util.LinkedList; public class Demo3_LinkedList { public static void main(String[] args) { LinkedList list = new LinkedList(); // 创建LinkedList list.addFirst("a"); // 在第一个位置添加 list.addFirst("b"); list.addFirst("c"); list.addFirst("d"); list.addFirst("e"); list.addFirst("f"); list.addLast("m"); System.out.println(list); // 打印链表 System.out.println(list.getFirst()); // 获取第一个值 System.out.println(list.getLast()); // 获取最后一个值 System.out.println(list.removeFirst()); // 从链表中移除第一个值并返回该值 System.out.println(list.removeLast()); // 从链表中移除最后一个值并返回该值 System.out.println(list); // 打印链表 System.out.println(list.get(1)); // 按照索引获取值 } }
栈和队列数据结构
* 栈
* 先进后出
* 队列
* 先进先出
用LinkedList模拟栈数据结构
* A:案例演示
* 需求:请用LinkedList模拟站数据结构的集合,并测试
* 创建一个类将LinkedList中的方法封装
package com.heima.bean; import java.util.LinkedList; public class Stack { private LinkedList list = new LinkedList(); public void in(Object obj) { // 模拟进栈 list.addLast(obj); } public Object out() { // 模拟弹栈 return list.removeLast(); } public boolean isEmpty() { // 判断是否为空 return list.isEmpty(); } }
package com.heima.list; import java.util.LinkedList; import com.heima.bean.Stack; public class Demo4_LinkedList { public static void main(String[] args) { // 用LinkedList模拟栈结构 // demo1(); // 未封装 // demo2(); // 已封装 } public static void demo2() { Stack s = new Stack(); s.in("a"); // 进栈 s.in("b"); s.in("c"); s.in("d"); while (!s.isEmpty()) { // 判断栈结构是否为空 System.out.println(s.out()); // 弹栈 } } public static void demo1() { LinkedList list = new LinkedList(); list.addLast("a"); list.addLast("b"); list.addLast("c"); list.addLast("d"); // System.out.println(list.removeLast()); // System.out.println(list.removeLast()); // System.out.println(list.removeLast()); // System.out.println(list.removeLast()); while (!list.isEmpty()) { // 判断集合是否为空 System.out.println(list.removeLast()); // 如果不为空就弹栈一次 } } }
泛型(generic)概述和基本使用
* A:泛型概述
* B:泛型好处
* 提高安全性(将运行期的错误转移到编译期)
* 省去强转的麻烦
* C:泛型的基本使用
* < > 中放的必须是引用数据类型
* D:泛型使用注意事项
* 前后泛型必须一致,或者后面的泛型可以省略不写(JDK1.7的新特性 菱形泛型)
package com.heima.generic; import java.util.ArrayList; import java.util.Iterator; import com.heima.bean.Person; import com.heima.bean.Student; public class Demo1_Generic { public static void main(String[] args) { // demo1(); // 不使用泛型 // demo2(); // 使用泛型 } public static void demo2() { ArrayList<Person> list = new ArrayList<Person>(); // 要保证前后的泛型一致,泛型可以是Object,但一般不这么定义 list.add(new Person("张三", 23)); list.add(new Person("李四", 24)); Iterator it = list.iterator(); while (it.hasNext()) { Person stu = (Person) it.next(); // 每一次循环,next方法只能调用一次 System.out.println(stu.getName() + "..." + stu.getAge()); } } public static void demo1() { ArrayList list = new ArrayList(); list.add(110); list.add(true); list.add(new Person("张三", 23)); list.add(new Person("李四", 24)); Iterator it = list.iterator(); while (it.hasNext()) { Object object = (Object) it.next(); if (object instanceof Person) { Person p = (Person) object; // 向下转型 System.out.println(p.getName() + "..." + p.getAge()); } System.out.println(object); } } }
ArrayList存储字符串和自定义对象并遍历
* A:案例演示
* ArrayList存储字符串并遍历·泛型版
package com.heima.generic; import java.util.ArrayList; import java.util.Iterator; import com.heima.bean.Person; public class Demo2_Generic { public static void main(String[] args) { // demo1(); // demo2(); } public static void demo2() { ArrayList<Person> list = new ArrayList<Person>(); // 创建泛型为Person的集合对象 list.add(new Person("张三", 23)); list.add(new Person("李四", 24)); list.add(new Person("王五", 25)); list.add(new Person("赵六", 26)); Iterator<Person> it = list.iterator(); // 创建泛型为Person的迭代器 while (it.hasNext()) { Person person = (Person) it.next(); // 将迭代器中的每一个元素用person记录 System.out.println(person.getName() + "..." + person.getAge()); } } public static void demo1() { ArrayList<String> list = new ArrayList<String>(); // 创建泛型为String的集合对象 list.add("a"); list.add("b"); list.add("c"); list.add("d"); Iterator<String> it = list.iterator(); // 获取泛型为String的迭代器 while (it.hasNext()) { String string = (String) it.next(); System.out.println(string); } } }
泛型的由来
* A:案例演示
* 泛型的由来:通过Object转型问题引入
* 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题
* 也就是存在隐患,所以Java提供了泛型来解决这个安全问题
package com.heima.bean; public class Tool { private Object obj; public Tool() { super(); } public Tool(Object obj) { super(); this.obj = obj; } public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } }
package com.heima.generic; import com.heima.bean.Student; import com.heima.bean.Tool; import com.heima.bean.Worker; public class Demo3_Generic { public static void main(String[] args) { Tool t = new Tool(); // 创建工具类对象 t.setObj(new Student("张三", 23)); Worker w = (Worker) t.getObj(); // java.lang.ClassCastException,类型转换异常 System.out.println(w); } }
泛型类的概述及使用
* A:泛型类概述<T>
* 把泛型定义在类上
* B:定义格式
* public class 类名<泛型类型1, ...>
* C:注意事项
* 泛型类型必须是引用数据类型
* D:案例演示
* 泛型类的使用
package com.heima.bean; public class Tool<T> { private T t; public Tool() { super(); } public Tool(T t) { super(); this.t = t; } public T getT() { return t; } public void setObj(Object obj) { this.t = t; } }
泛型方法的概述和使用
* A:泛型方法概述
* 把泛型定义在方法上
* B:定义格式
* public <泛型类型> 返回类型 方法名 (泛型类型 变量名)
* C:案例演示
* 泛型方法的使用
package com.heima.bean; public class Tool<T> { private T t; public Tool() { super(); } public Tool(T t) { super(); this.t = t; } public T getT() { return t; } public void setObj(Object obj) { this.t = t; } public<Q> void show(Q q) { // 方法泛型需要与类的泛型一致,如果不一致就需要在方法上声明自己的泛型 System.out.println(q); } public static<Q> void print(Q q) { // 静态方法,类名调用,随着类的加载而加载,此时T还没有被赋值,因此必须要自己声明泛型 System.out.println(q); } }
泛型接口的概述和使用
* A:泛型接口概述
* 把泛型定义在接口上
* B:定义格式
* public interface 接口名<泛型类型>
* C:案例演示
* 泛型接口的使用
package com.heima.generic; public class Demo4_Generic { public static void main(String[] args) { Demo1 d1 = new Demo1(); // 推荐用这种 d1.show("a"); Demo2<String> d2 = new Demo2<>(); d2.show("b"); } } interface Inter<T> { // 定义了接口泛型 public void show(T t); } class Demo1 implements Inter<String> { // 推荐这种 @Override public void show(String t) { System.out.println(t); } } class Demo2<T> implements Inter<T> { // 没有必要再实现接口的时候给自己的类加泛型 @Override public void show(T t) { System.out.println(t); } }
泛型高级之通配符
* A:泛型通配符 <?>
* 任意类型,如果没用明确,那么就是Object以及任意Java类
* B:? extends E
* 向下限定,E及其子类
* C:? super E
* 向上限定,E及其父类
package com.heima.generic; import java.util.ArrayList; import java.util.List; import com.heima.bean.Person; import com.heima.bean.Student; public class Demo5_Generic { public static void main(String[] args) { //List<Object> list = new ArrayList<String>(); // 如果前面泛型为Object那么前后就不一致了 //List<?> list = new ArrayList<String>(); // 当右边的泛型是不确定的时候,左边可指定为? ArrayList<Person> list1 = new ArrayList<Person>(); list1.add(new Person("张三",23)); list1.add(new Person("李四",24)); list1.add(new Person("王五",25)); list1.add(new Person("赵六",26)); ArrayList<Student> list2 = new ArrayList<Student>(); list2.add(new Student("周七", 27)); list1.addAll(list2); // 向存储Person类对象的集合中存储 由其子类Student实例化的对象 System.out.println(list1); // list2.addAll(list1); // 将父类添加到子类中,会报错 } }
增强for循环的概述和使用
* A:增强for循环概述
* 简化数组和Collection集合的遍历
* B:格式
for(元素数据类型 变量 :数组或者是Collection集合) { 使用变量即可,变量就是元素 }
* C:案例演示
* 数组,集合存储元素用增强for循环遍历
* D:好处
* 简化遍历
package com.heima.jdk5; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import com.heima.bean.Person; public class Demo1_Foreach { public static void main(String[] args) { // demo1(); // 遍历数组 // demo2(); // 遍历自定义类的集合 public static void demo2() { ArrayList<Person> list = new ArrayList<Person>(); list.add(new Person("张三", 23)); list.add(new Person("李四", 24)); list.add(new Person("王五", 25)); list.add(new Person("赵六", 26)); for (Person person : list) { System.out.println(person.getName() + "..." + person.getAge()); } } public static void demo1() { int[] arr1 = { 11, 22, 33, 44, 55 }; for (int i : arr1) { // 底层为迭代器实现, fore 快速敲出 System.out.println(i); } ArrayList<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); for (String string : list) { // 快捷键 fore System.out.println(string); } } }
三种迭代能否删除
* A:普通for循环,可以删除,但是索引要 - -
* B:迭代器可以删除,但是必须使用迭代器自身的remove方法否则会出现并发修改异常
* C:增强for循环不能删除
package com.heima.jdk5; import java.util.ArrayList; import java.util.Iterator; public class Demo6_Foreach { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("b"); list.add("c"); list.add("d"); // demo1(list); // 普通for循环删除 // demo2(list); // while循环迭代器删除,迭代器变量定义在外 // demo3(list); // for循环迭代器删除,迭代器变量定义在内 // demo4(list); // 增强for循环 } public static void demo4(ArrayList<String> list) { // 3、增强for循环, 不能用来删除,只能用来遍历 for (String string : list) { if ("b".equals(string)) { // list.remove("b"); // 底层由迭代器实现,会出现并发修改异常 } } } public static void demo3(ArrayList<String> list) { for (Iterator<String> it2 = list.iterator() ; it2.hasNext();) { if ("b".equals(it2.hasNext())) { it2.remove(); } } System.out.println(list); } public static void demo2(ArrayList<String> list) { // 2、迭代器删除,注意一定要使用迭代器的删除方式,避免出现并发修改异常 Iterator<String> it = list.iterator(); while (it.hasNext()) { String string = (String) it.next(); if ("b".equals(string)) { it.remove(); } } System.out.println(list); } public static void demo1(ArrayList<String> list) { // 1、普通for循环删除,索引要 -- for (int i = 0; i < list.size(); i++) { if ("b".equals(list.get(i))) { list.remove(i--); // 注意i--,保证相邻的要删的元素不被漏删 } } System.out.println(list); } }
静态导入的概述和使用
* A:静态导入的概述
* B:格式
* import static 包名 . 类名 . 方法名;
* 可以直接导入道方法的级别
* C:注意事项
* 方法必须是静态的,如果有多个同名的静态方法,容易混淆,这个时候如果要用,必须加前缀
* 由此可见,意义不大,所以一般不用,但是要能看得懂
package com.heima.jdk5; import static java.util.Arrays.sort; import static java.util.Arrays.toString; public class Demo2_StaticImport { public static void main(String[] args) { int[] arr = { 55, 22, 33, 44, 11 }; sort(arr); // 使用Arrays类的sort排序 // System.out.println(toString(arr)); // 此时Arrays的toString和本类的toString冲突了 } }
可变参数的概述和使用
* A:可变参数的概述
* 定义方法的时候不知道该定义多少个参数
* B:格式
* 修饰符 返回值类型 方法名(数据类型 ... 变量名) { }
* C:注意事项
* 这里的变量其实是一个数组
* 如果一个方法有可变参数,那么,可变参数位于最后
package com.heima.jdk5; public class Demo3_ChangeableArgs { public static void main(String[] args) { int[] arr = { 11, 22, 33, 44, 55 }; print(2,arr); // 只打印了数组中的内容 System.out.println("-----------------"); print(2, 11, 22, 33, 44, 55); // 2没被打印 } /* * public static void print(int[] arr) { for (int i : arr) { * System.out.println(i); } } */ public static void print(int x, int ... arr) { // 可变参数其实是一个数组,可变参数必须放在最后 for (int i : arr) { System.out.println(i); } } }
Arrays工具类的asList() 方法的使用
* A:案例演示
* Arrays工具类的asList() 方法的使用,将数组转换为集合
* Collection中toArray(T[ ] t) 泛型版的集合转数组
package com.heima.jdk5; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Demo4_AsList { public static void main(String[] args) { // demo1(); // demo2(); // demo3(); } public static void demo3() { ArrayList<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); String[] arr = list.toArray(new String[4]); // 当转换数组时,数组的长度如果是小于等于集合的size,转换后的数组长度等于集合的size for (String string : arr) { // 如果数组的长度大于了size,分配的长度就是指定值 System.out.println(string); } } public static void demo2() { // int[] arr = {11,22,33,44}; // List<int[]> list = Arrays.asList(arr); Integer[] arr = {11,22,33,44}; List<Integer> list = Arrays.asList(arr); // 如果arr存储的是基本数据类型,那么整个arr会被当作一个元素转换成集合,而不会自动装箱 System.out.println(list); } public static void demo1() { String[] arr = { "a", "b", "c" }; List<String> list = Arrays.asList(arr); // 将数组转换成集合,虽然不能增删元素,但是可以用集合的思想操作数组,可以使用集合的其他方法 //list.add("d"); // 不能增加或减少元素 System.out.println(list); } }
集合嵌套之ArrayList嵌套ArrayList
* A:案例演示
* 集合嵌套之ArrayList嵌套ArrayList
package com.heima.jdk5; import java.util.ArrayList; import java.util.Iterator; import com.heima.bean.Person; public class Demo5_ArrayListArrayList { public static void main(String[] args) { ArrayList<ArrayList<Person>> list = new ArrayList<ArrayList<Person>>(); ArrayList<Person> first = new ArrayList<Person>(); first.add(new Person("杨幂", 30)); first.add(new Person("李冰冰", 33)); first.add(new Person("范冰冰", 20)); ArrayList<Person> second = new ArrayList<Person>(); second.add(new Person("黄晓明", 31)); second.add(new Person("陈坤", 32)); list.add(first); list.add(second); for (ArrayList<Person> a : list) { for (Person p : a) { // 循环嵌套循环 来遍历 集合嵌套集合 System.out.println(p); } } } }