集合的遍历-迭代器 List接口 泛型 List常见实现类 增强型for循环

回忆

  • java.util.Date
    • new Date()
    • new Date(long )
  • java.util.Calender
    • Calender.getInstance();
    • get
    • set
    • add
  • java.text.DateFormat
    • SimpleDateFormat
    • yyyy-MM-dd HH:mm:ss
    • parse
    • format
  • 包装类型
    • 首字母大写
    • Character
    • Integer
    • parseXxx的方法将字符串转换为对应的类型
    • String.valueOf()方法将对应的类型转换为字符串
  • System类
    • exit 退出程序
    • gc 垃圾回收
    • 当前毫秒数
    • copyArray 高效数组复制
  • Arrays工具类
    • toString 打印数组的内容
    • sort
    • binarySearch
    • 截取
    • 复制到一个新的长度
    • 批量填充

集合(很重要)

它比数组还要常用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Juv008Yc-1593268055637)(imges/image-20200627092825930.png)]

Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素

  • 一些 collection 允许有重复的元素,而另一些则不允许。
  • 一些 collection 是有序的,而另一些则是无序的。
  • JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 SetList)实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iYmyBx1T-1593268055642)(imges/image-20200627093137930.png)]

跟数组的对比

  • 数组:长度确定,类型确定。
    • 类型可以是基本类型、引用类型
  • 集合:长度不固定(最大的优势)
    • 元素类型只能是引用类型。

Collection接口的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jjggq7gL-1593268055645)(imges/image-20200627093608992.png)]

//1. 我如何得到Collection接口的实例呢?
创建一个Collection接口的实现类。比如:ArrayList

集合的遍历-迭代器

Iterator<E> iterator() 
          返回在此 collection 的元素上进行迭代的迭代器。 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RYdrTgJG-1593268055650)(imges/image-20200627100115131.png)]

注意:如果hashNext()返回了false的情况下,再继续调用next()方法会抛出异常: java.util.NoSuchElementException

//重点:关于集合的遍历,Java专门提供了一种迭代器
Iterator iterator = cc.iterator();
while(iterator.hasNext()){
    System.out.println(iterator.next());
}

List接口

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。允许重复的元素。

List集合的特点:有序、可重复。

 void add(int index, E element) 
          在列表的指定位置插入指定元素(可选操作)。 
 boolean addAll(int index, Collection<? extends E> c) 
          将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。 
 E get(int index) 
          返回列表中指定位置的元素。   
  int indexOf(Object o) 
          返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1int lastIndexOf(Object o) 
          返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。 
     
 ListIterator<E> listIterator() 
          返回此列表元素的列表迭代器(按适当顺序)。 
 ListIterator<E> listIterator(int index) 
          返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。 
 E remove(int index) 
          移除列表中指定位置的元素(可选操作)。 
E set(int index, E element) 
          用指定元素替换列表中指定位置的元素(可选操作)。 
List<E> subList(int fromIndex, int toIndex) 
          返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。      
/*
    需求: 定义包含 1 2 3 4 5 的集合
    遍历它,如果发现集合元素可以被2整除,在此元素的后面添加一个 -1.
 */

迭代器的异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXAICLKp-1593268055653)(imges/image-20200627112151496.png)]

本质原因:

  • 是使用迭代器进行迭代的过程中,未通过迭代器修改了集合的长度(一般就是插入的新的元素),迭代器并不知道。就会抛出并发修改异常。

解决方案有两种:

  • 用for循环实现。
  • 添加或删除操作必须通过迭代器来进行。
//1. 优先考虑迭代器
// 注意: nextIndex 要在next之前调用。
ListIterator iterator = cc.listIterator();
while (iterator.hasNext()){
    int i = iterator.nextIndex(); //当前迭代的位置
    Object next = iterator.next();
    Integer n = (Integer)next;
    if(n % 2 ==0){
        System.out.println(i+"发现了元素:"+n);
        //add
        //                cc.add(i, -1);
        //                cc.remove(i);
        //注意:改变长度的时候,不要直接调用集合的方法,而应该使用迭代器的方法
        iterator.add(-1);
    }
}

常见的数据结构

程序 = 数据结构 +算法;

  • 栈结构: 后进先出。
  • 队列:先进先出。
  • 数组: 特点是检索快,增删慢。
  • 链表:检索慢,增删快。
    • 单向链表
    • 双向链表
    • 循环链表
    • 双向循环链表
    • 二叉树: 最多两个子节点

List常见实现类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z73Mg5Mt-1593268055655)(imges/image-20200627114321784.png)]

  • Vector 是旧的List集合。 线程安全,效率低。

    • 旧的集合体系,就是API命名上多少有些差异,使用上没差异。

    • void addElement(E obj) 
               将指定的组件添加到此向量的末尾,将其大小增加 1int capacity() 
               返回此向量的当前容量。     
        void copyInto(Object[] anArray) 
               将此向量的组件复制到指定的数组中。 
      E elementAt(int index) 
               返回指定索引处的组件。 
      Enumeration<E> elements()   迭代
               返回此向量的组件的枚举。 
      E firstElement() 
               返回此向量的第一个组件(位于索引 0) 处的项)。 
          void insertElementAt(E obj, int index) 
               将指定对象作为此向量中的组件插入到指定的 index 处。 
           E lastElement() 
               返回此向量的最后一个组件。 
       void removeAllElements() 
               从此向量中移除全部组件,并将其大小设置为零。 
      boolean removeElement(Object obj) 
               从此向量中移除变量的第一个(索引最小的)匹配项。 
      void removeElementAt(int index) 
               删除指定索引处的组件。 
      protected  void removeRange(int fromIndex, int toIndex) 
                从此 List 中移除其索引位于 fromIndex(包括)与 toIndex(不包括)之间的所有元素。 
       void setElementAt(E obj, int index) 
                将此向量指定 index 处的组件设置为指定的对象。     
      
    • Enumeration elements = v.elements();
      while(elements.hasMoreElements()){
          System.out.println(elements.nextElement());
      }
      
    • 被ArrayList取代。线程不安全,效率高。

  • ArrayList 底层使用的是数组。【日常开发用的多】

  • LinkedList 底层使用的是链表。

    • void addFirst(E e) 
               将指定元素插入此列表的开头。 
      void addLast(E e) 
               将指定元素添加到此列表的结尾。 
      Iterator<E> descendingIterator() 
                返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。 
      E element() 
                获取但不移除此列表的头(第一个元素)。 
       E getFirst() 
                返回此列表的第一个元素。 
       E getLast() 
                返回此列表的最后一个元素。 
       boolean offer(E e) 
                将指定元素添加到此列表的末尾(最后一个元素)。 
       boolean offerFirst(E e) 
                在此列表的开头插入指定的元素。 
       boolean offerLast(E e) 
                在此列表末尾插入指定的元素。 
       E peek() 
                获取但不移除此列表的头(第一个元素)。 
       E peekFirst() 
                获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。 
       E peekLast() 
                获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。 
       E poll() 
                获取并移除此列表的头(第一个元素) 
       E pollFirst() 
                获取并移除此列表的第一个元素;如果此列表为空,则返回 null。 
       E pollLast() 
                获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。 
       E pop() 
                从此列表所表示的堆栈处弹出一个元素。 
       void push(E e) 
                将元素推入此列表所表示的堆栈。 
       E remove() 
                获取并移除此列表的头(第一个元素)。 
        E removeFirst() 
                移除并返回此列表的第一个元素。 
       boolean removeFirstOccurrence(Object o) 
                从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。 
       E removeLast() 
                移除并返回此列表的最后一个元素。 
       boolean removeLastOccurrence(Object o) 
                从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。 
          
      
      

    练习:

    • 去除集合中重复的字符串的值。(“hello”,“java”,“world”,“hello”,“java”,“test”) -> (“hello”,“java”,“world”,“test”)
    • 去除集合中重复的学生(name,age)。(new st1,st2,st3,st3,st4,st5)
      • 集合中的 indexof 也好 contains 方法也好,底层都是调用元素对象的 equals方法。
        • 如果不满足需求,需要按需重写 equals 方法。

泛型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m1QiINsA-1593268055656)(imges/image-20200627162914791.png)]

当不写泛型的时候,认为是Object。

        ArrayList arrayList = new ArrayList();
        //不写泛型的时候(为了先下兼容),认为元素类型就是Object,
        //等价于 ArrayList<Object>

        arrayList.add("hello");
        arrayList.add("world");
        arrayList.add(10);//Integer -> 装箱操作


        //问题就在于消费集合元素时,无法确定元素的类型。只能在运行时暴露异常信息。
        //为了解决此问题,Java语言就提供了泛型的技术,用来约束集合中元素的类型。
        // 并且它会将异常提前到编译期。

泛型的定义很简单,只要在原来的 接口 、类 上使用 <>的语法就可以产生 泛型接口、泛型类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vxjzsJio-1593268055657)(imges/image-20200627164317357.png)]

/*
 演示自己定义一个泛型类

 */
public class Demo2 {
    public static void main(String[] args) {
        //即使你是一个泛型类,也可以不指定泛型类型(默认就是Object)
        Class2 class2 = new Class2();
        class2.setAge("hello");
        Object age = class2.getAge();
        class2.method1("hello");


        //当在代码中提供了泛型以后,就可以使用泛型带来的好处
        // 类型绑定,将对应的类型确定下来
        Class2<Integer,String> clazz2 = new Class2<Integer, String>();
        //jdk 1.7 支持泛型推断
        Class2<Integer,String> clazz3 = new Class2<>();

//        clazz2.setAge("hello");//报错,编译期错误.
        clazz2.setAge(10);
        System.out.println(clazz2.getAge());
        clazz2.method1("hhhh");

    }
}


//尖括号中的标识符是自己起的,数量没有限制,用逗号分隔就行.
//只是从实践中,大家会使用一些见名知意的泛型标识:
//E-----element
//T-----    type
//Pk---- 主键
//有了泛型定义以后,所有类中出现类型的地方(成员类型、方法返回值、方法参数)可以直接使用泛型标识
class Class<T>{

}

class Class2<T,M>{
    private T age;

    public T getAge() {
        return age;
    }

    public void setAge(T age) {
        this.age = age;
    }

    public void method1(M m){
        System.out.println(m);
    }
}


/*
其实即使是一个普通的Java类(非泛型类),也支持在类中定义泛型方法。

语法格式:
    修饰符  <T> 返回值类型 方法名(参数类型 参数名,.....){


    }

   具体T的绑定,可以出现在: 返回值类型、参数类型上。


 */
public class Demo3 {
    public static void main(String[] args) {
        DemoMethod.eq("aaa", 10);
        Object o = DemoMethod.m2(2, 3);
    }
}


class DemoMethod{
    public static <T> boolean eq(T a,T b){
        return a==b;
    }

    public static <T> T m2(Integer a,Integer b ){
        return (T)null;
    }
}


增强型for循环

//经典的for循环
for(初始化部分;条件判断部分;条件更新){
    循环体;
}


//增强型for循环的语法
for(元素类型 变量名:可增强迭代的内容){
    访问变量名;
}
// 可增强迭代的内容: 数组、集合。

        int[] arr = {1,2,3,4,5};

        for(int item :arr){
            //特点: 在循环体中无法访问位置信息。
            System.out.println(item);
        }

        //Arrays工具类中,存在一个方法来进行数组转集合。
        List<int[]> ints = Arrays.asList(arr);
        //集合的元素类型是: int数组。
        for(int[] item:ints){
            System.out.println(Arrays.toString(item));
        }

注意事项:

  • 本质是使用迭代器来进行

  • 迭代前需要人为判断null的问题,否则报空指针异常。

    •     //所以,增强型for循环一般会配合一个if检查一起使用。
          if(arr!=null) {
              for (int item : arr) {
                  //特点: 在循环体中无法访问位置信息。
                  System.out.println(item);
              }
          }
      
      
  • 在迭代过程中,不能改变集合的长度。

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6VrG40mV-1593268055659)(imges/image-20200627171500638.png)]

可变参数(1.7)

方法声明中的参数类型后面跟 ...

从语法层面跟数组类似,但比数组灵活。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vjnsJKik-1593268055660)(imges/image-20200627172152467.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e5cb05QR-1593268055661)(imges/image-20200627172251782.png)]

注意事项:Arrays.asList的返回值类型不是我们学过的某个实现类,而是它自己的。

  • 不能add等修改。

  • 要想正常处理,必须再重新构造:

    • new ArrayList(Arrays.asList(…));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值