16.01 ArrayList存储字符串并遍历
ArrayList类概述:底层数据结构是数组,查询快,增删慢,线程不安全,效率高
ArrayList类是List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
例:
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList al = new ArrayList(); 6 al.add("hello"); 7 al.add("world"); 8 al.add("java"); 9 10 Iterator it = al.iterator(); 11 while(it.hasNext()) 12 { 13 String s = (String)it.next(); 14 System.out.println(s); 15 } 16 } 17 }
16.02 ArrayList存储自定义对象并遍历
例:
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList al = new ArrayList(); 6 al.add(new Student("小明",23)); 7 al.add(new Student("小红",15)); 8 al.add(new Student("旺财",16)); 9 al.add(new Student("小强",21)); 10 al.add(new Student("张三",23)); 11 12 Iterator it = al.iterator(); 13 while(it.hasNext()) 14 { 15 Student s = (Student)it.next(); 16 System.out.println(s.getName()+":"+s.getAge()); 17 } 18 } 19 }
16.03 Vector的特有功能
Vector类概述:底层数据结构是数组,查询快,增删慢,线程安全,效率低
Vector类特有功能
1. public void addElement(E obj):
将指定的组件添加到此向量的末尾,将其大小增加 1。 该方法被add()替代
2. public E elementAt(int index):
返回指定索引处的组件。 该方法被get()替代
3. public Enumeration<E> elements():
返回此向量的组件的枚举。 该方法被Iterator iterator()替代
补充知识:JDK升级的原因,安全、效率、简化书写
16.04 LinkedList的特有功能
LinkedList类概述:底层数据结构是链表,查询慢,增删快,线程不安全,效率高
LinkedList类特有功能
1. public void addFirst(E e):将指定元素插入此列表的开头。
2. public void addLast(E e):将指定元素添加到此列表的结尾。
3. public E getFirst():返回此列表的第一个元素。
4. public E getLast():返回此列表的最后一个元素。
5. public E removeFirst():移除并返回此列表的第一个元素。
6. public E removeLast():移除并返回此列表的最后一个元素。
16.05 去除ArrayList集合中的重复字符串元素案例1(两个集合)
去除ArrayList集合中字符串的重复值(字符串的内容相同)
思路:创建两个集合,遍历旧集合获取每一个元素,查看遍历到的元素在新集合中是否存在,存在不操作,不存在存入新集合
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList al = new ArrayList(); 6 7 al.add("java"); 8 al.add("hello"); 9 al.add("java"); 10 al.add("world"); 11 al.add("hello"); 12 al.add("java"); 13 //创建新集合 14 ArrayList newArray = new ArrayList(); 15 16 Iterator it = al.iterator(); 17 while(it.hasNext()) 18 { 19 String s = (String)it.next(); 20 if(!newArray.contains(s)) 21 newArray.add(s); 22 } 23 //遍历新集合 24 Iterator newit = newArray.iterator(); 25 while(newit.hasNext()) 26 { 27 String s = (String)newit.next(); 28 System.out.println(s); 29 } 30 } 31 }
16.06 去除ArrayList集合中的重复字符串元素案例2(单个集合)
去除ArrayList集合中字符串的重复值(字符串的内容相同),要求不能创建新集合
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList al = new ArrayList(); 6 7 al.add("java"); 8 al.add("hello"); 9 al.add("java"); 10 al.add("world"); 11 al.add("world"); 12 al.add("world"); 13 al.add("hello"); 14 al.add("java"); 15 16 for (int i = 0; i < al.size()-1; i++) 17 { 18 for (int j = i + 1; j < al.size(); j++) 19 { 20 if(al.get(i).equals(al.get(j))) 21 { 22 al.remove(j); 23 j--; 24 } 25 } 26 } 27 28 Iterator it = al.iterator(); 29 while(it.hasNext()) 30 { 31 String s = (String)it.next(); 32 System.out.println(s); 33 } 34 } 35 }
16.07 去除ArrayList集合中的重复自定义对象元素案例
去除ArrayList集合中自定义对象的重复值(对象的成员变量值都相同)
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList al1 = new ArrayList(); 6 7 al1.add(new Student("小明",23)); 8 al1.add(new Student("小明",23)); 9 al1.add(new Student("小红",15)); 10 al1.add(new Student("旺财",16)); 11 al1.add(new Student("小明",18)); 12 al1.add(new Student("旺财",16)); 13 al1.add(new Student("小强",21)); 14 15 ArrayList al2 = new ArrayList(); 16 //遍历旧集合 17 Iterator it = al1.iterator(); 18 while(it.hasNext()) 19 { 20 Student s = (Student)it.next(); 21 //contains()方法底层依赖的是equals()方法 22 //Object的equals()方法默认比较的是地址值 23 //需重写equals()方法 24 if(!al2.contains(s)) 25 al2.add(s); 26 } 27 //遍历新集合 28 Iterator it2 = al2.iterator(); 29 while(it2.hasNext()) 30 { 31 Student s = (Student)it2.next(); 32 System.out.println(s.getName()+":"+s.getAge()); 33 } 34 } 35 }
运行结果:
小明:23 小红:15 旺财:16 小明:18 小强:21
16.08 用LinkedList实现栈结构的集合代码
LinkedList list = new LinkedList(); list.addFirst("hello"); list.addFirst("world"); list.addFirst("java"); Iterator it = list.iterator(); while(it.hasNext()) { System.out.println(it.next()); }
16.09 用LinkedList模拟栈数据结构的集合并测试案例
自己定义一个集合类,底层可以使用LinkedList
public 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 Practice { public static void main(String[] args) { MyStack ms = new MyStack(); ms.add("hello"); ms.add("world"); ms.add("java"); while(!ms.isEmpty()) { System.out.println(ms.get()); } } }
16.10 泛型概述和基本使用
例:
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList al = new ArrayList(); 6 al.add("hello"); 7 al.add("world"); 8 al.add("java");//String 9 al.add(3);//Integer 10 11 Iterator it = al.iterator(); 12 while(it.hasNext()) 13 { 14 //ClassCastException 15 String s = (String)it.next(); 16 System.out.println(s); 17 } 18 } 19 }
上面的代码会报错,因为存储在al集合中的元素有String及Integer类型,在遍历的时候都当做String类型处理,所以报错。如果在创建对象的时候就明确元素的数据类型就不会出现问题了,在Java中这种技术成为泛型。
泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。
格式:<数据类型>:此处的数据类型只能是引用类型
例:
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList<String> al = new ArrayList<String>(); 6 al.add("hello"); 7 al.add("world"); 8 al.add("java"); 9 10 Iterator<String> it = al.iterator(); 11 while(it.hasNext()) 12 { 13 String s = it.next(); 14 System.out.println(s); 15 } 16 } 17 }
好处:
1:把运行时期的问题提前到了编译期间
2:避免了强制类型转换
3:优化了程序设计,解决了黄色警告线
16.11 ArrayList存储字符串并遍历泛型版
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList<String> al = new ArrayList<String>(); 6 al.add("hello"); 7 al.add("world"); 8 al.add("java"); 9 10 Iterator<String> it = al.iterator(); 11 while(it.hasNext()) 12 { 13 String s = it.next(); 14 System.out.println(s); 15 } 16 System.out.println("-----"); 17 for (int i = 0; i < al.size(); i++) 18 { 19 String s = al.get(i); 20 System.out.println(s); 21 } 22 } 23 }
16.12 ArrayList存储自定义对象并遍历泛型版
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 //泛型推断 6 // ArrayList<Student> al = new ArrayList<>(); 7 ArrayList<Student> al = new ArrayList<Student>(); 8 9 al.add(new Student("小明",23)); 10 al.add(new Student("小红",15)); 11 al.add(new Student("旺财",16)); 12 al.add(new Student("小强",21)); 13 14 Iterator<Student> it = al.iterator(); 15 while(it.hasNext()) 16 { 17 Student s = it.next(); 18 System.out.println(s.getName()+":"+s.getAge()); 19 } 20 } 21 }
16.13 通过Object转型问题引入泛型
早期的时候,我们使用Object来代表任意的类型。
向上转型是没有任何问题的,但是在向下转型的时候其实隐含了类型转换的问题。
也就是说这样的程序其实并不是安全的。所以Java在JDK5后引入了泛型,提高程序的安全性。
16.14 泛型类的概述及使用
泛型类:把泛型定义在类上
格式:public class 类名<泛型类型1,...>
注意:泛型类型必须是引用类型
例:
1 public class ObjectTool<R> 2 { 3 private R obj; 4 5 public R getObj() 6 { 7 return obj; 8 } 9 10 public void setObj(R obj) 11 { 12 this.obj = obj; 13 } 14 }
测试:
ObjectTool<String> ot = new ObjectTool<String>(); ot.setObj("hello"); System.out.println(ot.getObj());
16.15 泛型方法的概述和使用
泛型方法:把泛型定义在方法上
格式:public <泛型类型> 返回类型方法名(泛型类型 ...)
例:
1 //泛型方法,参数类型与类的类型一致,类上的是什么类型,方法的参数类型就是什么类型 2 public void show(R r) 3 { 4 System.out.println(r); 5 } 6 //泛型方法,参数类型与类的类型不一致,类上的类型与方法的参数类型无关 7 //该方法可以接受任意类型 8 public <T> void method(T t) 9 { 10 System.out.println(t); 11 }
测试:
ObjectTool<String> ot1 = new ObjectTool<String>(); ObjectTool<Integer> ot2 = new ObjectTool<Integer>(); ObjectTool<Boolean> ot3 = new ObjectTool<Boolean>(); ot1.show("hello");//类上的是什么类型,方法的参数类型就是什么类型 ot2.show(25); ot3.show(true); System.out.println("----"); //类上的类型与方法的参数类型无关 ot1.method("hello"); ot1.method(23); ot1.method(true);
16.16 泛型接口的概述和使用
泛型接口:把泛型定义在接口上
格式:public interface 接口名<泛型类型1...>
//泛型接口 public interface Inter<T> { public abstract void show(T t); } //实现类第一种情况:已经知道是什么类型的 public class InterImpl implements Inter<String> { @Override public void show(String t) { System.out.println(t); } } //第一种情况测试: public class InterDemo { public static void main(String[] args) { Inter<String> i = new InterImpl(); i.show("hello"); } } //实现类第二种情况:还不知道是什么类型的 public class InterImpl<T> implements Inter<T> { @Override public void show(T t) { System.out.println(t); } } //第二种情况测试: public class InterDemo { public static void main(String[] args) { Inter<String> i1 = new InterImpl<String>(); Inter<Integer> i2 = new InterImpl<Integer>(); i1.show("hello"); i2.show(23); } }
16.17 泛型高级之通配符
泛型通配符<?>: 任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E: 向下限定,E及其子类
? super E: 向上限定,E及其父类
例:
public class Practice { public static void main(String[] args) { // 泛型如果明确的写的时候,前后必须一致 Collection<Object> c1 = new ArrayList<Object>(); // Collection<Object> c2 = new ArrayList<Animal>();//错误 // Collection<Object> c3 = new ArrayList<Dog>();//错误 // Collection<Object> c4 = new ArrayList<Cat>();//错误 // ? 表示任意的类型都是可以的 Collection<?> c5 = new ArrayList<Object>(); Collection<?> c6 = new ArrayList<Animal>(); Collection<?> c7 = new ArrayList<Dog>(); Collection<?> c8 = new ArrayList<Cat>(); // ? extends E:向下限定,E及其子类 // Animal及Animal的子类 // Collection<? extends Animal> c9 = new ArrayList<Object>();//错误 Collection<? extends Animal> c10 = new ArrayList<Animal>(); Collection<? extends Animal> c11 = new ArrayList<Dog>(); Collection<? extends Animal> c12 = new ArrayList<Cat>(); // ? super E:向上限定,E及其父类 // Animal及Animal的父类 Collection<? super Animal> c13 = new ArrayList<Object>(); Collection<? super Animal> c14 = new ArrayList<Animal>(); // Collection<? super Animal> c15 = new ArrayList<Dog>();//错误 // Collection<? super Animal> c16 = new ArrayList<Cat>();//错误 } } class Animal {} class Dog extends Animal {} class Cat extends Animal {}
16.18 增强for的概述和使用
JDK5的新特性:自动拆装箱,泛型,增强for,静态导入,可变参数,枚举
增强for概述:简化数组和Collection集合的遍历
格式:
for(元素数据类型变量 : 数组或者Collection集合)
{使用变量即可,该变量就是元素}
例:
int[] arr = {11,22,33,44,55}; //增强for for(int x : arr) { System.out.println(x); }
好处:简化遍历
注意事项:增强for的目标要判断是否为null
16.19 ArrayList存储字符串并遍历增强for版
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList<String> al = new ArrayList<String>(); 6 al.add("hello"); 7 al.add("world"); 8 al.add("java"); 9 10 for(String str : al) 11 { 12 System.out.println(str); 13 } 14 } 15 }
16.20 ArrayList存储自定义对象并遍历增强for版
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 ArrayList<Student> al = new ArrayList<Student>(); 6 7 al.add(new Student("小明",23)); 8 al.add(new Student("小红",15)); 9 al.add(new Student("旺财",16)); 10 al.add(new Student("小强",21)); 11 12 for(Student s : al) 13 { 14 System.out.println(s.getName()+":"+s.getAge()); 15 } 16 } 17 }
16.21 静态导入的概述和使用
格式:import static 包名….类名.方法名;可以直接导入到方法的级别
例:
1 import static java.lang.Math.abs; 2 import static java.lang.Math.max; 3 import static java.lang.Math.pow; 4 5 public class Practice 6 { 7 public static void main(String[] args) 8 { 9 System.out.println(abs(-10)); 10 System.out.println(max(20,30)); 11 System.out.println(pow(2,3)); 12 } 13 }
注意事项:
1.方法必须是静态的
2.如果有多个同名的静态方法,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。
16.22 可变参数的概述和使用
可变参数概述:定义方法的时候不知道该定义多少个参数
格式:修饰符返回值类型方法名(数据类型… 变量名){}
例:
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 int result1 = sum(11,22,33); 6 int result2 = sum(11,22,33,44); 7 int result3 = sum(11,22,33,44,55); 8 System.out.println(result1); 9 System.out.println(result2); 10 System.out.println(result3); 11 } 12 //可变参数,其实就是一个数组 13 public static int sum(int... a) 14 { 15 int result = 0; 16 for(int x : a) 17 { 18 result += x; 19 } 20 return result; 21 } 22 }
注意:
1.这里的变量其实是一个数组
2.如果一个方法有可变参数,并且有多个参数,那么,可变参数必须是最后一个
16.23 Arrays工具类的asList()方法的使用(数组转集合)
Arrays工具类中的一个方法:public static <T> List<T> asList(T... a)
例:
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 String[] strArray = {"hello","world","java"}; 6 List<String> list = Arrays.asList(strArray); 7 for(String s : list) 8 { 9 System.out.println(s); 10 } 11 System.out.println("-----"); 12 //可变参数 13 List<String> list2 = Arrays.asList("hello","world"); 14 for(String s : list2) 15 { 16 System.out.println(s); 17 } 18 } 19 }
运行结果:
hello world java ----- hello World
注意事项:虽然可以把数组转成集合,但是集合的长度不能改变。
16.24 集合嵌套存储和遍历元素的案例代码实现
集合的嵌套遍历ArrayList嵌套ArrayList
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 // 创建大集合 6 ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>(); 7 8 //创建第一个集合 9 ArrayList<Student> al1 = new ArrayList(); 10 al1.add(new Student("小明",23)); 11 al1.add(new Student("小红",12)); 12 al1.add(new Student("小强",26)); 13 al1.add(new Student("旺财",14)); 14 //第一个集合添加到大集合 15 bigArrayList.add(al1); 16 17 //创建第二个集合 18 ArrayList<Student> al2 = new ArrayList(); 19 al1.add(new Student("唐僧",40)); 20 al1.add(new Student("孙悟空",28)); 21 al1.add(new Student("猪八戒",29)); 22 al1.add(new Student("沙僧",27)); 23 //第二个集合添加到大集合 24 bigArrayList.add(al2); 25 26 //创建第三个集合 27 ArrayList<Student> al3 = new ArrayList(); 28 al1.add(new Student("宋江",40)); 29 al1.add(new Student("吴用",35)); 30 al1.add(new Student("高俅",30)); 31 al1.add(new Student("李师师",22)); 32 //第三个集合添加到大集合 33 bigArrayList.add(al3); 34 35 // 遍历集合 36 for (ArrayList<Student> array : bigArrayList) 37 { 38 for (Student s : array) 39 { 40 System.out.println(s.getName() + "---" + s.getAge()); 41 } 42 } 43 } 44 }
16.25 产生10个1-20之间的随机数要求随机数不能重复案例
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 // 创建产生随机数的对象 6 Random r = new Random(); 7 8 // 创建一个存储随机数的集合。 9 ArrayList<Integer> array = new ArrayList<Integer>(); 10 11 // 定义一个统计变量。从0开始。 12 int count = 0; 13 14 // 判断统计遍历是否小于10 15 while (count < 10) 16 { 17 //先产生一个随机数 18 int number = r.nextInt(20) + 1; 19 20 //判断该随机数在集合中是否存在。 21 if(!array.contains(number)) 22 { 23 //如果不存在:就添加,统计变量++。 24 array.add(number); 25 count++; 26 } 27 } 28 29 //遍历集合 30 for(Integer i : array) 31 { 32 System.out.println(i); 33 } 34 } 35 }
16.26 键盘录入多个数据在控制台输出最大值案例
1 public class Practice 2 { 3 public static void main(String[] args) 4 { 5 // 创建键盘录入数据对象 6 Scanner sc = new Scanner(System.in); 7 8 // 键盘录入多个数据,不知道多少个,所以用集合存储 9 ArrayList<Integer> array = new ArrayList<Integer>(); 10 11 // 以0结束只要键盘录入的数据是0,我就不继续录入数据了 12 //定义一个记录变量 13 int count = 1; 14 while (true) 15 { 16 System.out.println("请输入第"+(count++)+"个数据"); 17 int number = sc.nextInt(); 18 if (number != 0) 19 { 20 array.add(number); 21 } 22 else 23 break; 24 } 25 26 // 把集合转成数组 27 // public <T> T[] toArray(T[] a) 28 Integer[] i = new Integer[array.size()]; 29 // Integer[] ii = array.toArray(i); 30 array.toArray(i); 31 System.out.println("排序前的数组是:" + arrayToString(i)); 32 // 对数组排序 33 // public static void sort(Object[] a) 34 Arrays.sort(i); 35 36 // 获取该数组中的最大索引的值 37 System.out.println("排序后的数组是:" + arrayToString(i) + " " 38 +"最大值是:"+ i[i.length - 1]); 39 } 40 41 //遍历数组的方法 42 public static String arrayToString(Integer[] i) 43 { 44 StringBuilder sb = new StringBuilder(); 45 46 sb.append("["); 47 for (int x = 0; x < i.length; x++) 48 { 49 if (x == i.length - 1) 50 { 51 sb.append(i[x]); 52 } 53 else 54 { 55 sb.append(i[x]).append(", "); 56 } 57 } 58 sb.append("]"); 59 return sb.toString(); 60 } 61 }
运行结果:
请输入第1个数据 25 请输入第2个数据 15 请输入第3个数据 45 请输入第4个数据 56 请输入第5个数据 58 请输入第6个数据 48 请输入第7个数据 0 排序前的数组是:[25, 15, 45, 56, 58, 48] 排序后的数组是:[15, 25, 45, 48, 56, 58] 最大值是:58