Java 集合 一

集合 只能装载引用类型的对象  对于基本类型byte shor int long float double char boolean 都只能自动装箱后存储

 

Collection接口    的方法

add( e)  尝试向集合添加元素 ,若成功则返回true

remove( e) 尝试删除集合中的元素 ,若成功则返回true

clear( ) 清空集合中的元素 

contains(e ) 元素是否在集合中 

size( ) 集合大小 

toArray( ) 集合元素转为数组元素 返回得到数组 Object[ ] array

 被List接口  Set接口 继承

被ArrayList  LinkedList  HashSet  LInkedHashSet 具体实现

 

 

ArrayList  LinkedList的三种遍历方式

1.迭代器遍历

import java.util.ArrayList;
import java.util.Iterator;

        ArrayList<String> arr = new ArrayList<String> ();
        arr.add("abc");//只能添加String类型的对象
        arr.add("it");
        arr.add("it");
        
        Iterator<String> it = arr.iterator();
        
        while(it.hasNext()){
            System.out.println(it.next());
        }

/* for循环写法

for(Iterator<String> it2 = arr.iterator(); it2.hasNext();){
System.out.println(it.next());
}

*/

//不管是while循环 还是for循环 都是用同一个迭代器对象去集合中取元素 (it和it2变量名指向的是同一个对象)
//因此一旦while循环 迭代器对象已经对集合遍历了一遍 那么再用for循环中的同一迭代器再去取元素 就会报错 java.util.NoSuchElementException 因为 迭代器只能取一遍!

 

2. for循环

3.增强型 for循环 (foreach Java 1.5版本引入   这是因为 1.5引入了 Iterable接口 该接口成为了 Collection List  Set接口的 父接口       Iterable的作用就是增强for循环!  )

增强型for

 好处 :代码简化 方便对容器进行遍历

 弊端: 没有索引 无法对容器中的指定元素进行操作

迭代器  Java1.2版本引入  成为了 Collection的父类接口   

该接口中抽象方法  hasNext( )  next( ) 是由具体的ArrayList  LinkedList  HashSet  LInkedHashSet 类来实现的

该接口的对象(接口没有对象  这里指的是实现类的对象)例如ArrayList这个实现类中  重写了方法  iterator( )   该方法可以返回实现类对象  即 Iterator<String> it = new ArrayList<String> ().iterator( )

迭代器 是集合通用的 获取其元素的方式——取元素前先判断是否有元素存在,有则取出,直到全部取出(一旦开始取就只能向下取,只能从头到尾取一遍,且在取的过程中 集合长度不能发生变化)

 

 

 

由于集合是存储任意类型的对象,因此集合中什么都可存  即存Object类型的对象

对集合中元素迭代获取时,得到的也是Object obj = it.next( ),  这种父类对象没办法使用其子类对象的特有方法  为了使用这些方法 必须向下转型 从Object类型 -> 子类类型  例如 String s =(String)it.next()  对象s才能使用 s.length()方法

 

为防止 向下转型时出现异常  我们可以对集合使用泛型,从而约束了集合中对象元素的类型统一, 这样就避免了迭代器取值后的类型强制转换

类型强制转换后 运行时发生 ClassCastException异常

 

import java.util.ArrayList;
import java.util.Iterator;

        ArrayList arr = new ArrayList();
        arr.add("abc");//只能添加String类型的对象
        arr.add("it");
        arr.add("it");// String类型
        arr.add(5);// int类型 自动封箱为 Integer类型
        
        Iterator it = arr.iterator();
        
        while(it.hasNext()){
            String str = (String)it.next();//强制类型转换!
            System.out.println(str.length());
        }

 泛型 只是编译时对类型的约束,编译后运行时 并不存在泛型,因此 java的泛型是一种伪泛型  不同于C++中的真泛型

  ArrayList<String> arr

  arr.add(" ")  如果添加的不是String类型 则编译失败,只有添加对象的类型正确 才能编译通过  编译后的.class文件中没有泛型 因此对于java的反编译文件  你是看不到泛型存在的 ┭┮﹏┭┮

 

        ArrayList<String> list = new ArrayList<String>();//ArrayList类 就是一个带泛型的类
        
        String[] arr = new String[list.size()];//String类型的数组 数组长度=集合的长度
        String[] result = list.toArray(arr);//将集合元素存储到指定数据类型的数组中  这个是一个带泛型的方法 public <T> T[] toArray(T[] a){ } 
        
        
        
        //带有泛型的接口
        
        public interface List <E>{
            abstract boolean add(E e);
        }
        
        //对于这种接口的实现 
        //1.先实现接口,不理会泛型 由调用者在创建 实现类 对象时 指定泛型中的数据类型
        public class ArrayList<E> implements List<E>{
            
        }
        //2.在实现接口的同时,就指定好泛型中的数据类型
        public class Xxx implements List<String>{
            
        }
        

 

使用泛型的好处

将运行时的异常 转移到编译时期的编译失败

避免强制转型的麻烦

 

 

 

 

泛型的通配符 ? extends  类型的类名   传参的类型 必须都继承自 已限定的父类  上限被限制

泛型的通配符 ?super  类型的类名   传参的类型 必须是限定子类的父类或超类  下限被限制

 

posted @ 2020-05-17 23:04  CherryYang  阅读(129)  评论(0编辑  收藏  举报