Java基础程序——集合和泛型

目录

一、集合(Collection)

1.1、概述

1.2、集合继承关系图

1.3、集合的方法

二、迭代器

2.1、迭代器概述

2.1、迭代器的实现原理

2.3、集合迭代中的转型

三、增强for循环

3.1、增强for循环遍历数组

3.2、增强for循环遍历集合

 四、泛型

4.1、泛型的定义和使用

4.2、 擦拭法

4.3、泛型类 

4.4、泛型方法

4.5、泛型的接口 

 4.6、泛型的好处

4.7、泛型的通配符

4.8、泛型的限定

五、List接口

5.1、List接口介绍

5.2、List接口的常用方法

六、迭代器的并发修改



一、集合(Collection)

1.1、概述

集合是Java中提供的一种容器,用来存储多个数据


1.2、集合继承关系图

  • ArrayList继承了抽象类AbstractList,同时实现了List接口,List接口继承了Collection接口。
  • Collection接口为最顶层集合接口
  • Collection接口的子类:List接口、Set接口
  • List接口常用的子类有:ArrayList类、LinkedList类
  • Set接口常用的子类有:HashSet类、LinkedHashSet类


1.3、集合的方法

  • boolean.add(E e)   添加元素到集合
  • int size()   返回集合中元素的个数
  • Object[] toArray()   将集合转成数组
  • boolean contains(Object o) 判断集合中是否有该元素
  • void clear()   清空集合
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<String>();
        collection.add("abc");
        collection.add("a");
        collection.add("b");
        collection.add("c");
        collection.add("c");
        collection.add("abc");   // 集合中可以存储重复元素
        // 返回集合中元素的个数
        System.out.println(collection.size());
        // 转换成数组形式
        Object[] objects = collection.toArray();
        System.out.println(Arrays.toString(objects));
        // 是否包含abc
        System.out.println(collection.contains("abc"));
        // 删除某个元素
        collection.remove("abc");  // 移除第一个为“abc”的元素
        System.out.println(collection);

        Collection<String> c = new ArrayList<>();
        c.add("c");
        collection.removeAll(c); // 移除所有为“c”的元素
        System.out.println(collection);

        // 清空集合
        collection.clear();
        System.out.println(collection.size());   // 清空后集合元素个数为0
    }

二、迭代器

2.1、迭代器概述

  • Java提供了很多个集合,这些集合采取的存储方式不同,我们要取这些集合中的元素,可以通过一种通用的获取方式来完成
  • Collection集合的通用获取方式,在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,然后继续判断,直到集合中的元素全部取出,这种方式就叫迭代
  • 每种集合的底层的数据结构不同,比如ArrayList是数组,LinkedList底层是链表。但无论哪种集合,都会有判断是否有元素及取出元素的动作,所以Java提供了一个迭代器定义了统一判断元素和取元素的方法。

2.1、迭代器的实现原理

  • 集合中的迭代器:获取集合中元素的方式
  • Iterator接口:两个方法
  1. hasNext()   判断集合中是否还有元素,有则返回true
  2. next()  取出集合中下一个元素
  • 找Iterator接口的实现类

        Collection定义了一个方法:Iterator iterator();

         以ArrayList为例:

    public static void main(String[] args) {
        Collection<String> collection =  new ArrayList();
        collection.add("a");
        collection.add("b");
        collection.add("c");
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        
        // for循环写法
        // 集合在前面就被取了,集合中元素就就没有了
        for(;iterator.hasNext();){
            System.out.println(iterator.next());
        }
    }

2.3、集合迭代中的转型

  • 在使用集合时,需要注意:
  1. 集合中存储的其实都是对象的地址
  2. 集合中也可以存储基本数值,是因为出现了基本类型的包装类,它提供了自动装箱的操作,本质上,集合中的元素都是基本数值的包装类对象
  • 存储时提升了Object。取出时要使用元素的特有内容,必须向下转型
        Collection<String> collection =  new ArrayList();
        collection.add("a");
        collection.add("b");
        collection.add("c");
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()){
            String next =(String)iterator.next();
            System.out.println(next);
            System.out.println(next.length());
        }

 注意:如果集合中存储了多种类型对象,这时向下转型会发生类型转换异常

  • Iterator接口也可以使用<>,来控制迭代元素的类型

三、增强for循环

3.1、增强for循环遍历数组

  • 增强for循环是JDK1.5新特性,JDK1.5版本后,出现新的接口java.lang.Iterable
  • Iterable作用就是实现增强for循环
  • 格式:
for(数据类型 变量名:数组或集合){}
  • 代码示例:
        String[] strArr = {"1","2","a","b"};
        for(String str : strArr){
            System.out.println(str);
        }
  •  增强for循环的好处和弊端

好处:代码减少,方便对容器的遍历

弊端:没有索引,不能操作容器里面的元素


3.2、增强for循环遍历集合

遍历集合的方式与数组一样

List<Person> list = new ArrayList();
list.add(new Person("小镭",20));
list.add(new Person("小黑",18));  
for(Person p : list){
   System.out.println(p.toString());
}

 四、泛型

4.1、泛型的定义和使用

  • 定义:泛型就是定义之初用符号表示不具体的类型,在使用的时候才动态地指定类型。       
  • 作用:是一种安全机制,是一种书写规范
  • 使用:指明集合中存储的数据类型
Collection<String> collection = new ArrayList<String>();

4.2、 擦拭法

  • 泛型是一种类似于“模板代码”的技术。Java语言的泛型实现方式是擦拭法(Type Erasure)
  • 泛型只在编译时存在,编译后就被擦除。在编译之前可以限制集合类型起到作用。
Collection<String> collection = new ArrayList<String>();
编译后:
Collection collection = new ArrayList();

4.3、泛型类 

  • 定义格式
修饰符 class 类名<代表泛型的变量> {
}
例如:API中的ArrayList
public class ArrayList<E> {
   public boolean add(E e) {}
   public E get(int index) {}
}
  • 使用格式:创建对象的时候,确定泛型的类型
ArrayList<String> list = new ArrayList<String>();
// 此时,变量E的值就是String类型
public class ArrayList<String> {
   public boolean add(String e) {}
   public String  get(int index) {}
}

ArrayList<Integer> list = new ArrayList<Integer>();
// 此时,变量E的值就是Integer类型
public class ArrayList<Integer> {
   public boolean add(Integere) {}
   public Integer get(int index) {}
}

4.4、泛型方法

  • 定义方法
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){}
  •  泛型方法的使用
ArrayList集合中的方法:
public <T> T[] toArray(T[] a) {}
  •  使用格式:调用方法时,确定泛型的类型
ArrayList<String> list = new ArrayList<String>();
String[] arr = new String[10];
String[] result = list.toArray(arr);
// 此时变量T为String类型
public <String> String[] toArray(String[] a) {}

// 变量T可以与定义集合的泛型不同
ArrayList<String> list = new ArrayList<String>();
Integer[] arr = new Integer[10];
Integer[] result=  list.toArray(arr);
// 此时,变量T的类型为Integer类型
public <Integer> Integer[] toArray(Integer[] a) {}

4.5、泛型的接口 

  • 泛型接口的格式
修饰符 interface 接口名<代表泛型的变量>{
    // 抽象方法
}

例如:
public interface List<E>{
  boolean add(E e);
}
  •  泛型类的使用
  1. 实现类实现接口,同时指定泛型类型
  2. 实现类实现接口,但不指定泛型,那么这个类也变成了泛型
比如 ArrayList实现了List接口,但没有指定泛型
public class ArrayList<E> implements List<E>{}

 4.6、泛型的好处

  • 将运行时期的异常(ClassException),转移到了编译时期,使编译失败
  • 避免了类型强转的麻烦
Collection<String> collection =  new ArrayList();
collection.add("a");
collection.add("b");
collection.add("c");
collection.add(1);   // 会编译失败   当即和明确类型后,存放不同类型编译会报错
// 当集合明确了类型时,迭代器就会知道具体遍历的元素类型
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()){
    Stringnext = iterator.next();
    System.out.println(next);
 }

4.7、泛型的通配符

需求:封装一个方法,可以遍历参数为任意类型的ArrayList

public static void method(ArrayList<?> list){
   // 遍历逻辑
   for(Object o : list){
        System.out.println(o);
    }
}

 当不知道使用什么类型来接收元素时,此时使用  ?  (?表示通配符)


4.8、泛型的限定

  • <? extends XXX> 限定的是父类,上限限定,表示可以传递XXX及其子类
  • <? super XXX> 限定的是子类,下限限定,表示可以传递XXX及其父类

五、List接口

5.1、List接口介绍

特点:

  • List是一个元素存取有序的集合                                                                                                     例如,存元素的顺序是11、22、33,那么集合中元素的存储顺序就是11、22、33
  • List是带有索引的集合,通过索引就可以精确的操作集合中的元素
  • 集合中可以存重复的元素,通过元素equals方法,来比较是否为重复元素。

List接口的常用子类

  • ArrayList
  • LinkedList

5.2、List接口的常用方法

  • 添加元素
  1. add(Object o)  向集合末尾处,添加指定元素
  2. add(int index, Object o);   向集合指定索引处,添加指定元素,原有元素依次后移
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add(1,"c");
        System.out.println(list);
  • 删除元素
  1. remove(Object o)  指定元素对象从集合中删除,返回值为布尔(boolean)类型
  2. remove(int index)  将指定索引处的元素从集合中删除,返回值为被删除的元素
        boolean result1 = list.remove("a");
        System.out.println(result1);
        String result2 =  list.remove(0);
        System.out.println(result2);
  •  替换元素
  1. set(int index, Object o);  将指定索引处的元素替换成指定元素,返回值为替换前的元素
        String result3 = list.set(0, "java");
        System.out.println(result3);
        System.out.println(list);
  •  查询元素
  1. get(int index);  获取指定索引处的元素,并返回查询元素
System.out.println(list.get(0));

六、迭代器的并发修改

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        System.out.println(list);
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
            if("a".equals(next)){
                list.add("xiaolei");   // 会报错  并发修改异常
            }
        }
    }

运行上述代码,会发生  java.util.ConcurrentModificationException

原因是在迭代过程中,使用了集合的方法对集合元素进行了操作,导致迭代器并不知道集合的变化而引发数据的不确定性。

并发修改异常的解决办法:

  1. 在迭代过程中,不适用集合的方法操作元素
  2. 若一定要在迭代中操作元素,可以通过ListIterator迭代器来完成。
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值