一、 迭代器
- 迭代器的增删作用于原集合
- 用迭代器遍历集合 , 用指针的挪动来获取对应的元素,通过标记这个元素是否可以用来操作 去操作原集合。
- 在迭代过程中不允许直接操作原集合。
- forEach --- 本质上也是做迭代遍历 ,如果一个对象能使用增强for循环,那么这个类必须实现 Iterable。
- JDK1.5的新特性之一。
/* * 迭代器练习 */ public class IteratorTest_01 { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("张三"); list.add("李四"); //获取迭代器对象 Iterator<String> iterator = list.iterator(); //通过迭代器遍历集合 //判断是否有下一个元素 while(iterator.hasNext()){ //挪动指针,获取元素 String s = iterator.next(); System.out.println(s); //移除当前元素 ---- 作用于原集合 // iterator.remove(); //在迭代过程中 ,不允许直接操作原集合 爆java.util.ConcurrentModificationException异常 list.remove(s); list.add("王五"); } System.out.println(list); } }
二、 泛型
- 学名: 参数化类型 --- 顶级泛型接口 ParameterizedType --- JDK1.5新特性之一。
- 起强制限定的作用。 提高运行和编译的效率。
- 用具体类型来替换泛型的操作 --- 泛型的擦除
- 使用泛型之后效率略低 ,多了泛型的推导和擦除过程。
/* * 泛型的定义 * 泛型在定义时只要符合标识符的命名规则即可 ,但习惯上是使用一个大写字母表示泛型 * T type * E Elements * K key * V value * R result * 当定多个泛型的时候,泛型之间用","隔开 * */ public class GenericTest_01 { public static void main(String[] args) { } } class Demo<T> { private T t; public Demo() { // t = new T(); //错误 , 因为不知道具体的类型 ,所以JVM无法分配具体的内存空间。 } //泛型可以用作返回值类型 public T getT() { return t; } //泛型可以用作参数 public void setT(T t) { this.t = t; } //参数类型不确定 ,希望传入任意类型的参数之后 ,转换为T类型 //不能定义正在一个类上 ,为当前方法定义一个属于当前方法的泛型 private <E> T change(E e) { return (T)e; } //参数类型确定 ,但返回值类型不确定 private <R>R change2 (T t){ return (R)t; } //参返都不确定 private <A,B>B change3(A a){ return (B)a; } }
- 泛型的继承 -- ?:表示泛型的通配符 , 表示此时需要泛型 ,但是不能确定类型
/* * 泛型类的继承 * */ public class GenericTest_02 { public static void main(String[] args) { List<Integer> list1 = Arrays.asList(1,3,5,7,4,3,2); List<Double> list2 = Arrays.asList(1.0,34.0,55.0,7.0,5.0,4.0,3.0); it(list1); it(list2); } //泛型不向下兼容 泛型Number不能接受数值类型的值 // ? extends Number 表示传入的这个类或接口 是Number 的子类 // 无论是类还是接口 ,这里一律用extends // Number规定了 泛型的上限 public static void it(List<? extends Number> list) { //由于不确定子类的类型 ,所以不能向集合中添加元素 ,只能添加null // list.add(4); // list.add(null); for(Number n : list ){ System.out.println(n); } } //可以传入String及其父类 // ? super 类\接口 表示 可以传入 这个类的子类\接口 元素 // 规定了泛型的下限 //规定了下限之久能够添加元素 //同一个泛型不能既规定上限 , 有规定下限 public static void it1(List<? super String> list){ } }
- 是JDK1.5的新特性之一
三、 Map<K , V>映射
- 映射 。 一个键对应一个值 --- map中的元素是以键值对的形式存在的。
- 键唯一 , 值唯一 。
- Map本身不是集合 , 但是集合框架中的一员。
- 集合框架中包含了集合 、映射以及操作集合和映射的工具 。
- Entry --- 代表键值对的接口 --- Map中的内部接口
- 一个Map对象实际上是由多个Entry对象组成的。
- HashMap ** 重点 **
- 允许值为null , 允许键为null。
- 默认初始容量为16 , 加载因子为0.75f , 每次扩容一倍 。 本身是一个异步式线程不安全的映射。
- HashTable ** 记住 **
- 任何非null值都可以作为键和值 --- 键值都不允许为null。
- 默认初始容量为11 , 加载因子为0.75f , 容量超过75% 时 开始扩容 , 本身是一个同步式线程安全的映射。
- 效率低
- 是 java中最早的映射。
- ComcurrenHashMap
- 异步式线程安全的映射
- Dictionary是所有映射的父类。
/* * Map * */ public class MapTest_01 { public static void main(String[] args) { //表示 键为String类型 , 值为 Integer类型 Map<String ,Integer> map = new HashMap<String , Integer>(); //添加元素 map.put("a", 1); map.put("b", 2); map.put("c", 3); map.put("d", 4); //覆盖元素 map.put("a", 5); //将所有的值放入一个Collection集合 System.out.println("map中所有值:"+map.values()); //获取键值对的个数 System.out.println("map中键值对的个数:"+map.size()); //判断映射是否为空 System.out.println("map是否为空:"+map.isEmpty()); //根据键获取对应的值 System.out.println("c对应的值是:"+map.get("c")); //判断映射中是否包含指定的键 System.out.println("map中是否有d:"+map.containsKey("d")); //删除元素 map.remove("b"); //清空映射 map.clear(); //映射中的toString方法做过重写 System.out.println(map.toString()); } }
package com.tj.tedu; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /* * map遍历的三种方式 * */ public class MapTest_02 { public static void main(String[] args) { //表示 键为String类型 , 值为 Integer类型 Map<String ,Integer> map = new HashMap<String , Integer>(); //添加元素 map.put("a", 1); map.put("b", 2); map.put("c", 3); map.put("d", 4); //方式一 Set<String> keySet = map.keySet(); for( String key : keySet){ System.out.println(key+"="+map.get(key)); } System.out.println("-----------------------------------"); //方式二 Set<Entry<String, Integer>> entrySet = map.entrySet(); for(Entry e : entrySet){ System.out.println(e.getKey()+"="+e.getValue()); } System.out.println("-----------------------------------"); //方式三 Set<Entry<String, Integer>> entrySet2 = map.entrySet(); Iterator<Entry<String, Integer>> iterator = entrySet2.iterator(); while(iterator.hasNext()){ Entry<String, Integer> next = iterator.next(); System.out.println(next.getKey()+"="+next.getValue()); } } }
练习:输入一个数以及对应个数的Integer键值对 ,输出要求:键从小到大排序 , 如果出现了重复的键 , 则要求对应的值求和 。// 输入一个数以及对应个数的Integer键值对 ,输出要求:键从小到大排序 , 如果出现了重复的键 , 则要求对应的值求和 。 public class Test_03 { public static void main(String[] args) { //在Scanner类中 , 除了nextLine()方法以外 , 其余的方法是以空格作为 结束符 Scanner in = new Scanner(System.in); System.out.println("请输入数据的个数 :"); int count = in.nextInt(); System.out.println("请依次输入数据,中间以,隔开:"); in.nextLine(); List<String> l = new ArrayList<String>(); for(int i = 0 ; i<count ;i++){ l.add(in.nextLine()); } //排序 l.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return new Integer(o1.split(",")[0])-new Integer(o2.split(",")[0]); } }); //放入Map如果键相同 , 则值求和 Map<Integer , Integer> map = new HashMap<Integer, Integer>(); for(int i = 0 ; i<count ; i++){ Integer key = new Integer(l.get(i).split(",")[0]); Integer value = new Integer(l.get(i).split(",")[1]); if(map.containsKey(key)){ map.put(key, map.get(key)+value); }else{ map.put(key, value); } } System.out.println(map); } }