首页 > 技术文章 > Java的集合框架

zkdayup 2017-10-26 22:06 原文

Java集合框架综述

1:集合框架(Collection Framework)

首先要知道 集合代表的是一组对象,和数组差不多 但是数组的长度是固定不变的,而集合是可以变换长度的,比如说:集合就是一根金箍棒,可长可短, 数组就像是一根普通的木棍,长度是固定的,不能变长或者变短。在Java的集合框架中定义了一套规范用来操作集合和具体实现细节,在这里呢也可以把集合想象成一个数据库 ,它有“增删改查”四种操作 ,在本章呢会介绍集合框架的基本类和接口和一些的基本操作方法。

2:集合框架的两大接口(Collection和Map)

1.Collection接口

Collection表示一组对象 ,这些对象也称为collection元素,一个collection允许有重复的值,而另一些则不允许,一些collection是有序的,而有一些是无序的,在Java中没有直接实现collection的 但是它提供了两个子接口 这两个子接口继承了collection接口,那是哪两个接口呢?

ヾ(✿゚▽゚)ノ  这里介绍两个collection接口的子接口    List   和   Set  

 

1.1ArraysLIst类

ArrayList是List的一个实现类。每一个ArrayList实例都有一个容量,该容量是指用来存储列表的数组大小,它总是等于或者小于列表的大小,随着向ArrayList不断添加元素,其容量也不断的增大。这里ArrayList它跟数组有很多相同点,到底有什么相同点和不同点呢?如下

那知道ArrayList的概念 怎么创建一个ArrayList集合呢?  定义语法如下:

 1 //创建ArrayList集合 2 List list = new ArraysList(0); 

 在创建ArrayList集合的时候需要导入包:

//导入包
import
java.util.ArrayList; import java.util.List;

知道了创建ArrayList集合 那怎么向集合里添加元素呢  开始说过java集合框架中定义了一套规范来实现“增伤改查”那怎么实现具体操作呢?下面介绍ArrayList集合的常用方法:

ArraysLIst 集合的常用方法
Arrays.asList(); 将数组装换为集合 
add(Object value); 添加元素
add(int index,Object value)向指定位置插入元素 
get(int index);通过下标获取元素 
set(intindex,Object value);修改指定位置的元素 
remove(int index); 移除集合中指定位置的元素
remove(Object o);从集合中移除第一次出现的指定元素(如果存在) 
removeAll(collection<?>c);从列表中移除制动的collection 中包含的所有元素
Clear (); 移除集合中所有的元素
//遍历ArrayList
foreach(Object item : list){
    //通过get()方法获取元素
}

需要注意的是: 1.存储的元素类型都是Object类型

        2.ArrayList集合中是可以添加重复的值,这个跟数组是一样的

                          3. 它的初始容量为10的空列表

1.2HashSet类

 HashSet是一个哈希集是set的一个重要实现类 它不保证顺序恒久不变,也就是说是无序的,它允许使用NUll元素  但是只能有一个。而且他还不能有重复的值。set中 添加某个对象 无论添加多少次  最终只会保留一个该对象(的引用) 并且 保留的是第一次添加的那一个。既然是无序的所以它没有索引,不能通过索引获取元素。同样跟ArrayList一样它储存的类型也是Object类型。

那怎么创建一个Hashset呢?  代码如下:

//创建HashSet(哈希集)
HashSet hashset= new HashSet();

在创建HashSet实例时需要导入包:

import java.util.HashSet;

 

以下是HashSet类的一些常用方法   如下图:

add(Object value) 如果此 set中尚未包含指定元素,则添加指定元素 它的返回值是Boolean类型

clear() 移除所有元素

remove(Object o)如果指定元素存在于此 set 中,则将其移除 它的返回值是Boolean类型

size()获取set中的元素的数量  返回值是int

isEmpty()判断该set中是否包含任何元素 返回值是boolean类型

iterator() 返回对此 set 中元素进行迭代的迭代器。

大家看到Hashset并没有直接获取元素的方法,因为他是无序的 没有索引,这里我们用iterator()方法迭代获取数据,那怎么用呢?代码如下:

 

import java.util.Iterator;//导包

itIterator i = hash.iterator(); while(i.hasNext()){ String str = (String)i.next();//需要强转 }

这里需要注意的是  HashSet里储存是Object类型  需要什么数据类型 就强转成什么数据类型

上面的是通过Iterator()方法进行迭代  看起来比较麻烦  所以还有一种渐变的方法  通过foreach迭代器进行获取数据 代码如下:

foreach(Object item in hash){

      //获取数据        

}

 上面是Collection接口中的两个子接口 List和Set 下面介绍另一个接口  Map

2.Map接口

 

Map提供了一种映射关系 其中的元素是以键值对(Key-value)的形式存储的 能够实现根据key快速查找Value

Map中的键值对以Entry类型的对象实例形式存在

健(key值)不可重复 value值可以
一个值可以跟很多的key进行映射关系 但一个健(key值)最多只能映射到一个值(value)

 2.1 HashMap类

 HashMap是map的一个重要实现,也是最常用的 基于哈希表实现 它的Entry对象是无序排序的,Key值和value值都可以为null 但是一个HashMap只能有一个kay值为null的映射(key值不可重复)

介绍了HashMap类的概念 那怎么创建呢?  代码如下:

//导入包
import java.util.HashMap;
//创建Hashmap
HashMap hash = new HashMap();

那HashMap类中有什么常用方法呢?如下:

get(Object key); 指定健获取所映射的值
Clear();从此映射中移除所有的映射关系
remove(Object key);从此映射中移除指定键的映射关系(如果存在)
size();  获取此映射中的键-值映射的关系
put(K key,V value) 在此映射中关联指定的值与指定键  如果该映射以前包含了一个该键的映射关系  从而达到修改的功能
entrySet 语法: public Set<Map.Entry<K,V>> enttryset()  返回map中所有的键值对
KeySet  语法: public Ste<k>keyset()  返回此映射中所包含的键的set视图
getKey()  获取键 
getValue() 获取值

如何向HashMap中添加映射关系呢?如下:

//创建HashMap
HashMap hashmap =  new HashMap();
//通过HashMap类的Put()方法添加映射关系
hashmap.put(1, "张三");

这里需要注意的是:1.向HashMap中添加映射关系时  需要指定一个Key(键)指定一个Value(值)从而达到映射关系,

                                 2.同样这里的健(key)和值(value)都是object类型,

如何获取HashMao中的数据呢?HashMap是键值对可以通过获取键的方法获取数据代码如下:

//通过HashMap类的gat(object key)获取值
System.out.println(hashmap.get(1));

那如何遍历HashMap中的元素呢? 用foreach迭代器实现 代码如下:

//遍历HashMap的Key值获取数据
for (Object item:hashmap.keySet()) {
    System.out.println(hashmap.get(item));
            
}

其他的方法就不一一测试了  ( ̄▽ ̄)~* 

那现在有一个问题 比如如下代码:

List list = new ArrayList();
list.add("qqyumidi");
list.add("corn");
list.add(100);
 for (int i = 0; i < list.size(); i++) {
       String name = (String) list.get(i); //1
       System.out.println("name:" + name);
}

定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

以上代码中有两个问题:

A.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

B.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

那有什么办法可以使集合能够约束元素类型呢 并达到安逸不报错呢?在Collection和Map中有出现了一个泛型集合。

3.什么是泛型?

泛型也可以理解为“参数化类型”,类型的参数化,就是可以把类型像方法的参数那样传递。这一点意义非凡。

那它有什么作用呢? :泛型使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常。

怎么定义个泛型集合呢?把上面的代码修改如下:

List<String> list = new ArraysList<String>();//定义泛型的语法 

list.add("aaa");

list.add("bbb");

list.add(1111);//1

foreach(String item : list){

   System.out.println(item);    

}

根据上面的代码 得到 定义泛型集合的语法:

List<E> list  = new ArraysList<E>();
在List<>尖括号里是要对集合数据类型的约束
<E>中的E表示类型形参,可以接收具体的类型实参
上面的代码集合类型是String类型 那么代码“1”我们添加一个int类型的数据 这样编译器是会报错的,因为在定义泛型的时候 限制的是String类型 所以只能添加String类型的数据,
所以我们总结: 当泛型进行了数据类型约束的时候 不能添加其他的数据类型,否则编译器会报错。
那么HashSet也可以定义泛型,对元素的数据类型进行约束,那怎么创建HashSet泛型呢?语法如下:
//创建HashSet泛型
HashSet<E> hashSet = new HashSet<E>();

同样是对HashSet中的元素进行数据类型约束 用法如上,具体方法 请往上看HashSet集合的方法。

需要注意的是:

                 1.泛型集合中 不能添加泛型规定的类型及其子类型以外的对象 否则会报错
                 2.泛型集合中的限定类型 不能使用基本数据类型
                 3. 可以通过使用包装类限定允许存入的基本数据类型

以上是Collection家族的集合和泛型,那么Map家族有泛型吗?  答案是肯定的  

HashMap如何定义泛型呢  我们用代码实现一下  代码如下:

//定义HashMap泛型
HashMap<K, V> Hashmap = new HashMap<K, V>();

在HashMap<K,V>

K代表的是Key(键)的数据类型,

V代表的值(value)的数据类型,

也就是说 K键的数据类型必须是规定的数据类型不能是其他的数据类型,值(value)也是一样。

以上是对泛型的介绍,这里在介绍一下Map中的contains方法:

contains方法 某个序列是否包含某个对象  如果包含则返回true  如果不包含则返回faslse

HashMap中:

ContainsKey(object key); 获取此映射是否包含对于指定建的映射关系
ContainsValue(object values); 获取此映射是否在此映射中存在的值

具体怎么使用呢?请看代码:

Student类

public class Student {
    //学号
    private String id;
    
    //姓名
    private String name;
    
    
    public String getId() {
        return id;
    }


    public void setId(String id) {
        this.id = id;
    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }

    public Student(String id,String name){
        
        this.id=id;
        this.name=name;
        
    }
    

}

 

test类

import java.util.HashMap;
/**
 * ClassName: TestContains 
 * @Description: TODO测试 Map接口的HashMap类的Contains方法
*/
public class TestContains {
    
    public static void main(String[] args) {
        
        //创建HashMap泛型   键的类型约束是String类型 值的类型约束是学生类(Student)
        HashMap<String, Student> hashmap  = new HashMap<String, Student>();
        //创建一个学生 张三
        Student zs = new Student("A1000", "张三");
        //向泛型中添加元素
        hashmap.put("1",zs);
        //检查是否存在键Key 1
        boolean yesno = hashmap.containsKey("1");
        //输出结果
        System.out.println("Does it contain key1:"+yesno);
        //检查是否包含值 Value “张三”这个学生
        boolean yesno1 = hashmap.containsValue(zs);
        //输出结果
        System.out.println("Does it contain values‘张三’:"+yesno1);
        
    }
}

这里我的HashMap中key的约束数据类型是String (这里大家注意下 泛型类型约束不能放基本数据类型 可以放数据类型的类 )value的类型约束是Student类的实例,也是就是说我定义的是学生类  里面只能放一个学生 要是放一个老师就不行。

言归正传 这里我使用HashMap中的Contains方法来判断泛型中是否包含某个键 或者包含某个对象,它的返回值类型就是Boolean类型,true或false;

接下来带大家认识两个接口和一个工具类:

1.Collections(工具类)

Collections工具类是java集合框架中 用来操作集合对象的工具类,这里我们只介绍一个方法sort();

在使用之前需要导入工具类的包 代码如下:

 

//导入包
import java.util.Collections;

 

sort()方法呢主要是排序 语法如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TetsCollectionsSort {
    public static void main(String[] args) {
        
        //创建ArrayList泛型
        List<String> list = new ArrayList<String>();
        //向集合里添加数据
        list.add("aasd");
        list.add("csfgsfd");
        list.add("zasd");
        list.add("gghg");
        //输出排序前
        System.out.println("排序前");
        for (String item : list) {
            System.out.println(item);
        }
        //进行排序
        Collections.sort(list);
        //排序后
        System.out.println("排序后");
        for (String item : list) {
            
            System.out.println(item);
            
        }
    }
}
这里发现这些字符串的顺序发生了变化 那么是怎么进行排序的呢?
答:
在排序String字符串的时候是比较首字母排序   如果首字母一样则比较第二个字符  如此往下,如果字符串的开头是数字,则比较数字的大小,数字在前,字母在后,
上面是java集合框架的Collections工具类的sort()方法的介绍,下面介绍一个接口
2.Comparable接口
前面介绍了Collections.sort()方法   而要实现序列的排序就要实现comparable接口下面就介绍Comparable接口
实现该接口表示,这个类的实例可以进行自然排序,
定义了默认的比较规则
其实现类需要compareTo()方法
compareTo
()方法返回整数表示大 负数表示小 0表示相等
一个生活的小案例 在学校里做广播体操时 一般学生的排列都是按照身高去排列,从矮到高排列 因此学生是可以进行比较的,那么我们想两个事物要进行比较,是不是要找到可以比较的方式呢?在我们比较连个事物的时候
会有一个默认的比较规则,称为自然排序,比如在学生排列的时候这个身高就是可以比较的特性,也是默认的比较规则,那么自然顺序就是身高之间的差异。
那么如何用代码实现呢? 代码如下:
Student类
public class Student{
    //学号
    private String id;
    
    //姓名
    private String name;
    
    
    public String getId() {
        return id;
    }


    public void setId(String id) {
        this.id = id;
    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }

    public Student(String id,String name){
        
        this.id=id;
        this.name=name;
        
    }
}
test类
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

/* ClassName: TestContains 
 * @Description: TODO测试comparable接口比较对象
 */
public class TestContains {

    public static void main(String[] args) {

        // 创建HashMap泛型 键的类型约束是String类型 值的类型约束是学生类(Student)
        List<Student> list = new ArrayList<Student>();
        // 创建两个学生 张三 李四
        Student zs = new Student("Z1000", "张三");
        Student ls = new Student("V1000", "李四");
        // 向集合中添加元素
        list.add(zs);
        list.add(ls);
        // 排列前
        for (Student item : list) {
            System.out.println("学号是:" + item.getId() + "姓名:" + item.getName());
        }
        // 排列
        Collections.sort(list);//1
        // 排序后
        for (Student item : list) {
            System.out.println("学号是:" + item.getId() + "姓名:" + item.getName());
        }

    }
}

这里呢我们的代码1处会报错的  是因为咱们的Student这个类没有实现comparable接口  所以我们要对Student这个类进行改造 修改后的代码如下:

public class Student  implements Comparable<Student>{
    //学号
    private String id;
    
    //姓名
    private String name;
    
    
    public String getId() {
        return id;
    }


    public void setId(String id) {
        this.id = id;
    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }

    public Student(String id,String name){
        
        this.id=id;
        this.name=name;
        
    }

  //重写comparable的comparato()方法
    @Override
    public int compareTo(Student o) {
        
        return this.id.compareTo(o.id);
    }
    

}

这里让Student这个类实现Comparable接口  因为接口都是抽象的 所以这里必须重写compareTo()方法  

这个方法实现  让学生的Id进行一个比较排列 返回整形  那么Test类输出如下:

排序前
学号是:Z1000姓名:张三
学号是:V1000姓名:李四
排序后
学号是:V1000姓名:李四
学号是:Z1000姓名:张三

这里的排序方法向上面介Collections.sort()方法一样

3.Comparator接口 ---- 比较工具
用于定义临时比较规则,而不是默认比较规则
其实现类需要实现Compare()方法
强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator 传递给 sort 方法
compare()方法返回整数表示大 负数表示小 0表示相等

具体实现comparator接口的代码如下:
StudentComparator类
import java.util.Comparator;

public class StudentComparator implements Comparator<Student>{

  //要实现Comparator接口必须要重写Compare()方法 @Override
public int compare(Student o1, Student o2) { //按照学生的姓名进行排列 return o1.getName().compareTo(o2.getName()); } }
Test类修改如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

/* ClassName: TestContains 
 * @Description: TODO测试comparable接口比较对象和comparator接口
 */
public class TestContains {

    public static void main(String[] args) {

        // 创建HashMap泛型 键的类型约束是String类型 值的类型约束是学生类(Student)
        List<Student> list = new ArrayList<Student>();
        // 创建两个学生 张三 李四
        Student zs = new Student("Z1000", "张三");
        Student ls = new Student("V1000", "李四");
        // 向集合中添加元素
        list.add(zs);
        list.add(ls);
        // 排列前
        System.out.println("排序前");
        for (Student item : list) {
            System.out.println("学号是:" + item.getId() + "姓名:" + item.getName());
        }
        // 排列
        Collections.sort(list);
        // 排序后
        System.out.println("排序后");
        for (Student item : list) {
            System.out.println("学号是:" + item.getId() + "姓名:" + item.getName());
        }
        //按照姓名排序如下
        System.out.println("按照姓名排序是:");
        Collections.sort(list,new StudentComparator());
        for (Student item : list) {
            System.out.println("学号是:" + item.getId() + "姓名:" + item.getName());
        }
        
    }
}

这里Collections.sort();时需要传递一个集合  和一个实现类的对象,

本章主要介绍Java集合框架的主要成员有:Collection接口  Map接口 Collections工具类  Comparable接口 Comparator接口

 

本章内容到此结束!!!

 




 

推荐阅读