三十、集合-Collecton接口

在前面我们学习了数组,数组可以保存多个元素,但在某些情况下无法确定到底要保存多少个元素,此时数组将不再适用,因为数组的长度不可变。为了保存这些数目不确定的元素,JDK中提供了一系列特殊的类,这些类可以存储任意类型的元素,并且长度可变,统称为集合。

一、ArrayList底层实现原理

ArrayList集合是程序中最常见的一种集合,它属于引用数据类型(类)。在ArrayList内部封装了一个长度可变的数组,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。

 /**

 * 模拟ArrayList底层实现基础方法
 
 */

public class MyArrayList{
 
     //基础数组长度设置
 
     private static final int CAPCITY=10;
 
    //底层数组
 
     transient Object[] elementData;
 
     //加入数据长度,不代表数组长度
 
     private int size;
 
      public MyArrayList(){
 
           this(10);
 
     }
 
     public MyArrayList(int size){
 
         //数组初始化
 
         elementData=new Object[size];
 
     }
 
 //数组扩容处理
 
     private void grow(int index){
 
         if(size==index){

                int capcity=elementData.length+(elementData.length>>1);
 
                 Object[] newArray=new Object[capcity];
 
                System.arraycopy(elementData, 0, newArray, 0, elementData.length);
 
                 elementData=newArray;

    }
 
     }

 //添加元素
 
    public void add(E e){

        grow(elementData.length);
 
         elementData[size++]=e;
 
    }
 
 }


二. ArrayList集合的创建

导包:import java.util.ArrayList;

创建对象:与其他普通的引用数据类型创建方式完全相同,但是要指定容器中存储的数据类型:
ArrayList<要存储元素的数据类型> 变量名 = new ArrayList<要存储元素的数据类型>();

  • 集合中存储的元素,只能为<>括号中指定的数据类型元素;

  • “<要存储元素的数据类型>”中的数据类型必须是引用数据类型,不能是基本数据类型;

image
  • 存储String类型的元素:ArrayList list = new ArrayList<String>();

  • 存储int类型的数据:ArrayList list = new ArrayList<Integer>();

三.ArrayList集合中常用方法

image
image
  • Xxx,代表定义ArrayList集合时,<>中所定义的数据类型

四.集合遍历

 for(int i = 0; i < list.size(); i++){
 
     //通过索引,获取到集合中每个元素
 
     int n = list.get(i);
 
     System.out.println(n);
 
}


五、集合的继承关系

查看ArrayList类发现它继承了抽象类AbstractList同时实现接口List,而List接口又继承了Collection接口。
Collection接口为最顶层集合接口了

源代码:

interface List extends Collection{

}

public class ArrayList extends AbstractList implementsList{

}

这说明我们在使用ArrayList类时,该类已经把所有抽象方法进行了重写。那么,实现Collection接口的所有子类都会进行方法重写。

Collecton接口常用的子接口有:List接口、Set接口

List接口常用的子类有:ArrayList类、LinkedList类

Set接口常用的子类有:HashSet类、LinkedHashSet类

image

六、Collection接口

既然Collection接口是集合中的顶层接口,那么它中定义的所有功能子类都可以使用。查阅API中描述的Collection接口。Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

继续查阅API,发现Collection接口中很多集合的操作方法,那么这些方法都具体能做什么呢?

1.Collection接口基本方法

image

这里我们不关心具体创建的Collection中的那个子类对象,这里重点演示的是Collection接口中的方法。

创建集合的格式:

方式1:Collection<元素类型> 变量名 = new ArrayList<元素类型>();

方式2:Collection 变量名= new ArrayList();

方式1创建的集合,只能存储<>中指定的元素类型,该方式为常用方式

方式2创建的集合,集合的元素类型默认为Object类型,即任何类型的元素都可以存储。

Collection接口中的方法演示:

 //创建集合

 Collectioncoll = new ArrayList();
 
 //1,往集合中添加对象元素。add(E e)方法,E代表创建集合时所指定的数据类型如,那么,E就代表String类型;创建集合时若没有指定数据类型,那么,E就代表Object类型。
 
 coll.add("sxt1");

coll.add("sxt2");
 
coll.add("sxt3");
 
 //把集合打印一下。
 
 System.*out*.println(coll); //打印结果为:[sxt1, sxt2, sxt3]

 System.*out*.println(coll.toString()); //打印结果为:[sxt1, sxt2, sxt3]
 
 //2,从集合中删除元素。remove(Object o)方法
 
 coll.remove("sxt2");  
 
 //删除后,集合元素为[sxt1, sxt3]
 
//3,判断集合中是否包含指定元素。contains(Object o)方法

 System.*out*.println(coll.contains("sxt1"));

 //打印结果为true
 
 System.*out*.println(coll.contains("sxt2"));
 
 //打印结果为false
 
 //4,获取集合元素个数。size()方法
 
 System.*out*.println(coll.size());
 
 //打印结果为2
 
 //5,返回包含集合中所有元素的数组。toArray()方法
 
 Object[] array= coll.toArray();
 
 //数组中的元素为{"sxt1","sxt3"}
 
//6,清除集合元素。remove()方法
 
 coll.clear();
 
 //清空后,集合元素为[],代表没有元素


七、获取集合中的元素的专业方式——迭代器Iterator

1. 迭代器概述

java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。

Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

2.迭代器的使用

集合中把这种取元素的方式描述在Iterator接口中。Iterator接口的常用方法如下:

image

hasNext()方法:用来判断集合中是否有下一个元素可以迭代。如果返回true,说明可以迭代。

next()方法:用来返回迭代的下一个元素,并把指针向后移动一位。

迭代集合元素图解:

image

迭代方式的代码体现:

在Collection接口描述了一个抽象方法iterator方法,所有Collection子类都实现了这个方法,并且有自己的迭代形式。

image
 //1,创建集合对象。
 
Collection coll = new ArrayList();
 
 coll.add("abc1");
 
 coll.add("abc2");
 
 coll.add("abc3");
 
 coll.add("abc4");
 
 //2.获取容器的迭代器对象。通过iterator方法。
 
 Iterator it =coll.iterator();
 
 //3,使用具体的迭代器对象获取集合中的元素。参阅迭代器的方法
 
 while(it.hasNext()){
 
    System.out.println(it.next());
 
}
 
/* 
 迭代器for循环的形式的使用 
for(Iterator it = coll.iterator();it.hasNext();  ) { 
   System.*out*.println(it.next()); 
 } 
 */

注意:在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生java.util.NoSuchElementException没有集合元素的错误。

3.增强for循环

增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

格式:

for(元素的数据类型 变量 : Collection集合or数组){

}

它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。

一:遍历数组

 int[] arr = newint[]{11,22,33};
 
 for (int n : arr) {   //变量n代表被遍历到的数组元素
 
    System.out.println(n);

 }

二:遍历集合

 Collectioncoll =newArrayList();
 
 coll.add("sxt1");
 
 coll.add("sxt2");
 
 coll.add("sxt3");

coll.add("sxt4");
 
 for(String str : coll){//变量Str代表被遍历到的集合元素
 
    System.*out*.println(str);
 
 }

增强for循环和老式的for循环有什么区别?

注意:新for循环必须有被遍历的目标。目标只能是Collection或者是数组。

建议:遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行 操作,使用老式for循环可以通过角标操作。

八、集合元素的向下转型

学习到这里,基本知道了Collection接口的简单使用。可是集合中可以存储任何对象,那么存放进去的数据都是还是原来类型吗?不是了,提升成了Object。

在使用集合时,我们需要注意以下几点:

集合中存储其实都是对象的地址。

集合中可以存储基本数值吗?

jdk1.5版本以后可以存储了。因为出现了基本类型包装类,它提供了自动装箱操作(基本类型à对象),这样,集合中的元素就是基本数值的包装类对象。

存储时提升了Object。取出时要使用元素的特有内容,必须向下转型:

 Collection coll =newArrayList();

 coll.add("abc");
 
 coll.add("aabbcc");
 
 coll.add("shsxt");
 
 Iterator it =coll.iterator();
 
 while (it.hasNext()) {
 
    //由于元素被存放进集合后全部被提升为Object类型
 
   //当需要使用子类对象特有方法时,需要向下转型
 
    String str = (String) it.next();
 
    System.*out*.println(str.length());
 
 }

注意:如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常。

提示:Iterator接口也可以使用<>来控制迭代元素的类型的。代码演示如下:

 Collectioncoll =**new**ArrayList();

 coll.add("abc");
 
 coll.add("aabbcc");
 
 coll.add("shsxt");
 
 Iteratorit = coll.iterator();
 
 while (it.hasNext()) {
 
    String str =  it.next();
 
 //当使用Iterator控制元素类型后,就不需要强转了。获取到的元素直接就是String类型
 
    System.*out*.println(str.length());
 
 }


九、Collections集合工具类

Collections是集合工具类,用来对集合进行操作。部分方法如下:


Collections集合工具类方法.png
  • public static <T> void sort(List<T> list) // 集合元素排序
    //排序前元素list集合元素 [33,11,77,55]
    Collections.sort( list );
    //排序后元素list集合元素 [11,33,55,77]

  • public static void shuffle(List<?> list) // 集合元素存储位置打乱
    //list集合元素 [11,33,55,77]
    Collections.shuffle( list );
    //使用shuffle方法后,集合中的元素为[77,33,11,55],每次执行该方法,集合中存储的元素位置都会随机打乱

十、 集合嵌套

集合嵌套并不是一个新的知识点,仅仅是集合内容又是集合,如Collection集合嵌套、Collection集合与Map集合相互嵌套、Map集合嵌套。

  • ArrayList嵌套 ArrayList
    ArrayList< ArrayList<String> >
    Collection< ArrayList<Integer> >
  • Map嵌套 ArrayList
    HashMap<String, ArrayList<Person>>
    ArrayList< HashMap<String, String>>
  • Map集合嵌套
    HashMap<String, HashMap<String,String>>
    HashMap<String, HashMap<Person,String>>

十一、 集合继承体系的面向对象思想

集合继承体系的面向对象思想.png
  • 接口:用来明确所有集合中该具有的功能,相当于在定义集合功能标准;
  • 抽象类:把多个集合中功能实现方式相同的方法,抽取到抽象类实现,具体集合不再遍写,继承使用即可;
  • 具体类:继承抽象类,实现接口,重写所有抽象方法,达到具备指定功能的集合。每个具体集合类,根据自身的数据存储结构方式,对接口中的功能方法,进行不同方式的实现。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容