Java学习笔记------集合(五)

该学习笔记是根据阿玮老师《黑马程序员Java零基础视频教程》总结出来的,非常感谢阿玮老师。

一. 集合简单介绍

  1. 简单介绍:集合和数组一样都相当于是一个容器,但集合可以自动扩容。集合和数组的对比:
    (1)数组的长度是固定的,集合的长度是可变的;
    (2)数组可以存储基本数据类型和引用数据类型;集合可以存储引用数据类型,不能直接存储基本数据类型,需要先将基本数据类型转为其对应的包装类。基本数据类型对应的包装类:byte–Byte、short–Short、char–Character、int–Integer、long–Long、float–Float、double–Double、boolean–Boolean。
  2. java中规定了很多种集合,例如:TreeSet、HashSet、HashMap、Vector、Collection、Map、LinkedHashSet、LinkedList和ArrayList等等。我们可以将集合大致上分为两大类:Collection集合、Map集合。其中,Collection属于单列集合;Map属于双列集合。所谓单列集合就是在添加数据的时候每次只能添加一个元素;所谓双列集合就是在添加数据的时候每次只能添加一对元素(两个元素–键值对,和python字典类似)。其实后面使用次数最多的就是HashMap和ArrayList

二. 单列集合

  1. 有图有真相
    Collection集合
    关于Collection的代码如下:
// Collection是一个接口,我们不能直接创建它的对象,只能创建它的实现类对象.
        Collection<String> collection = new ArrayList<>(); //通过多态的方式去创建Collection的对象
        // 添加元素
        collection.add("aaa");
        collection.add("bbb");
        collection.add("ccc");
        System.out.println(collection);

 // 删除元素:因为Collection里面定义的是共性的方法(List系列和Set系列,Set系列没有索引),不能通过索引删除元素,
 // 只能通过元素的对象进行删除。
        collection.remove("ccc");
        System.out.println(collection);

        // 判断集合中是否包含元素
        System.out.println(collection.contains("aaa"));

        // 清空元素
        collection.clear();
        System.out.println(collection);

        // 判断集合是否为空
        System.out.println(collection.size());
        System.out.println(collection.isEmpty());
/*
输出:
[aaa, bbb, ccc]
[aaa, bbb]
true
[]
0
true
*/
  1. Collection集合的遍历:迭代器遍历、增强for遍历、Lambda表达式遍历。
    *(1) 迭代器遍历:迭代器在java中的类是Iterator,迭代器是集合专用的遍历方式。我们可以通过一个方法(iterator())获取迭代器对象,默认指向当前集合的0索引;然后利用hasNext() 和 next 获取集合中每一个元素。迭代器不依赖索引。用代码解释迭代器:
// 迭代器代码解释:
        Iterator<String> it = list.iterator();
        boolean flag = it.hasNext();
// 通过hasNext()方法判断集合中是否存在元素(相当于创建了一个指针),存在返回true,不存在返回false.
        String str = it.next(); // next()做了两件事情:获取元素,并移动指针(也就是往后移动)
        System.out.println(str); //打印输出
/* 迭代器的注意细节:
(1)迭代器遍历完成,指针不会复位,也就说遍历完成迭代器的指针指向最后没有元素的位置.如果我们想要继续二次遍历集合,只能再次获取一个新的迭代器对象; 
(2)循环中只能使用一次next()方法;
(3)迭代器遍历时(也就是遍历过程中),不能使用集合的方法进行添加或者删除元素.
*/

迭代器遍历Collection集合代码如下:

// 创建集合并添加元素
        Collection<String> collection  = new ArrayList<>();
        collection.add("aaa");
        collection.add("bbb");
        collection.add("ccc");

        // 获取集合collection的迭代器对象,默认指向集合collection的0索引.
        Iterator<String> it = collection.iterator();
        while(it.hasNext()){ //如果集合有元素,it.hasNext()返回true,不存在元素返回false.
            String str = it.next(); // next()方法先获取元素,然后让指针往后移动.
            System.out.println(str);
        }

        // 产生一个新的迭代器对象.
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
            iterator.remove(); //通过迭代器删除元素
        }
        System.out.println(collection);
        System.out.println(collection.size());
/*
输出:
aaa
bbb
ccc
aaa
bbb
ccc
[]
0
*/
  • (2)增强for遍历
    增强for遍历:增强for遍历的底层就是迭代器,为了简化迭代器代码书写。增强for遍历是在JDK5之后出现的,其内部原理就是一个Iterator迭代器;所有的单列集合和数组才能使用增强for进行遍历。
// 增强for遍历的格式
// for(元素的数据类型 变量名: 数组或者集合){
//      
// }
// 创建集合并添加元素
        Collection<String> collection  = new ArrayList<>();
        collection.add("aaa");
        collection.add("bbb");
        collection.add("ccc");
        // 增强for遍历,这里的s只是一个第三方变量.
        for (String s : collection) {
            System.out.println(s);
        }
/*
输出:
aaa
bbb
ccc
*/
  • (3)时间紧任务重,所以Lambda表达式遍历(别看了,开始摆烂把。哈哈哈,这种方式先别看了,以后用到再说吧)
  1. List接口继承Collection接口,ArrayList类、LinkedList类、Vector类实现了List接口。由于List是一个接口,所以我们不能直接创建它的对象,只能创建它的实现类对象。关于ArrayList类、LinkedList类、Vector类的具体用法大家可以自行网上查一下。同理:Set集合和List集合级别一样都是接口,都存在对应的实现类。
  2. 泛型
    • 泛型是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。泛型中不能写基本数据类型,只能写引用数据类型,如果不写泛型类型,类型默认是Object。泛型的好处:统一数据类型;把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来。
    • 泛型的三种使用方式:泛型类、泛型方法、泛型接口。
      泛型
    • (1)泛型类的定义格式:修饰符 class 类名<泛型类型>{} 例子: public class ArrayList<E> 这里的E表示不确定类型;当我们使用ArrayList类创建对象时,E的类型就确定了。换句话说这里的E可以理解为变量,但不是用来记录数据的,而是记录数据类型的。
    • (2)泛型方法的定义格式:修饰符 <泛型类型> 返回值类型 方法名(泛型类型 变量名){} 例子:public <E> void show(E e){}。此处的E可以理解为变量,但不是用来记录数据的,而是记录类型的。调用该方法show()时,E的类型就确定了。
    • (3)泛型接口的定义格式:修饰符 interface 接口名<泛型类型>{} 例子:public interface List<E>{}。泛型接口的使用,方式1:实现类给出具体类型;方式2:实现类延续泛型,创建对象时再确定。
    • 泛型不具备继承性,但是数据具备继承性(使用下面代码理解)。泛型的应用场景:我们在定义类、方法、接口时,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。如果类型不确定,但是知道以后只能传递某个继承体系,就可以使用泛型的通配符< ? >
    • 定义泛型的时候使用A-Z中任何一个字母都可以,但是为了规范,大家约定俗成的把泛型字母定义如下
泛型字母作用
E(Element)表示集合中元素的类型
T(Type)通常用于表示类或方法的泛型类型
K(Key)
V(Value)
N(Number)数值类型
public class Test {
    public static void main(String[] args)  {
        // 泛型不具备继承性,但是数据具备继承性
        ArrayList<Ye> listYe = new ArrayList<>();
        ArrayList<Fu> listFu = new ArrayList<>();
        ArrayList<Zi> listZi = new ArrayList<>();

        show(listYe);
//show(listFu); // 会报错. 这是因为泛型不具备继承性,你在show()方法的泛型里面写的什么类型,就只能传递什么类型的数据.
//show(listFu); // 会报错  你写的Ye这个类,因此只能传递Ye这个类创建的ArrayList集合对象listYe,子类的不能传递
        listYe.add(new Ye());
        listYe.add(new Fu());
        listYe.add(new Zi()); //你可以往集合listYe里面添加Fu类的对象、Zi类的对象,这表明数据具备继承性.
    }

    public static void show(ArrayList<Ye> list){
    }
}

class Ye{}

class Fu extends Ye{}

class Zi extends Fu{}
public class Test {
    public static void main(String[] args)  {
        // 泛型不具备继承性,但是数据具备继承性
        ArrayList<Ye> listYe = new ArrayList<>();
        ArrayList<Fu> listFu = new ArrayList<>();
        ArrayList<Zi> listZi = new ArrayList<>();
        ArrayList<Student> listStu = new ArrayList<>();

        show(listYe);
        show(listFu);
//        show(listZi);
//        show(listStu);
/*        
将show()方法的泛型Ye修改为E代码不会报错.但是此时show(listStu);也不会报错,(我们的出发点只是将存在继承关系的
listYe、listFu、listZi放入到show方法中,根本不想让listStu调用成功.) 此时我们可以使用泛型的通配符"?",
 "?"也表示不确定的类型,使用方式有两种: ? extends E--表示可以传递E或者E所有的子类类型;
                                    ? super E--表示可以传递E或者E所有的父类类型.
    }
*/
//    public static <E> void show(ArrayList<E> list){
//    }

//    public static void show(ArrayList<? extends Ye> list){
//        // show(listStu);会报错.因为此时我们限定只能是Ye或者Ye的所有子类可以调用show方法.
//    }

    public static void show(ArrayList<? super Fu> list){
// show(listStu);show(listZi); 会报错.因为此时我们限定只能是Fu类或者Fu的所有父类可以调用show方法.
    }
}

class Student{}

class Ye{}

class Fu extends Ye{}

class Zi extends Fu{}
  1. 单列集合Collection使用场景总结
    Collection单列集合

三. 双列集合

  1. 简单介绍
    Map集合属于双列集合。双列集合的特点:(1)双列集合一次需要添加一对数据(两个元素),分别是键和值;(2)键不能重复,值可以重复;(3)键和值是一一对应的,每个键只能找到自己对应的值;(4)“键”+“值"这个整体我们称为"键值对"或者"键值对对象”,在java中叫做"Entry对象"。
    Map集合
        // Map是一个接口,接口是不能创建对象的,因此只能通过Map的实现类创建对象.
        Map<String,String> map = new HashMap<>();
        // 使用put()方法添加元素. 在添加数据时,如果键不存在,那么直接把键值对对象添加到map集合中,
        //           在添加数据时,如果键是存在的,那么就会把原有的键值对对象覆盖,会把被覆盖的值(旧值)进行返回.
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");
        map.put("令狐冲","东方不败");
        System.out.println(map);
        String str = map.put("令狐冲", "任盈盈");
        System.out.println(str);
        System.out.println(map);

        // 使用remove()方法删除元素. 返回键对应的值
        String s = map.remove("郭靖");
        System.out.println(s);
        System.out.println(map);

        System.out.println(map.containsKey("杨过"));
        System.out.println(map.containsKey("郭靖"));
        System.out.println(map.containsValue("小龙女"));
        System.out.println(map.containsValue("黄蓉"));
/*
输出:
{令狐冲=东方不败, 杨过=小龙女, 郭靖=黄蓉}
东方不败
{令狐冲=任盈盈, 杨过=小龙女, 郭靖=黄蓉}
黄蓉
{令狐冲=任盈盈, 杨过=小龙女}
true
false
true
false
*/
  1. Map集合的遍历方式:键找值、键值对、Lambda表达式。
// Map是一个接口,接口是不能创建对象的,因此只能通过Map的实现类创建对象.
        Map<String,String> map = new HashMap<>();
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");
        map.put("令狐冲","东方不败");
        System.out.println(map);

        // 1. 键找值
        // 先通过keySet()获取所有的键,把这些键放到一个单列集合set中
        // 2.增强for遍历
        Set<String> set = map.keySet();
        for (String key : set) {
            System.out.println(key+"="+map.get(key));
        }
        // 2.迭代器遍历
//        Iterator<String> iterator = set.iterator();
//        while(iterator.hasNext()){
//            String key = iterator.next();
//            System.out.println(key+"="+map.get(key));
//        }

        // 键值对
        // 通过entrySet()获取所有的键值对对象,返回一个Set集合
        // 2.增强for遍历
        Set<Map.Entry<String, String>> entry = map.entrySet(); //Set<Map.Entry<String, String>>泛型嵌套
        for (Map.Entry<String, String> entries : entry) {
            String key = entries.getKey();
            String value = entries.getValue();
            System.out.println(key+"="+value);
        }
        //2.迭代器遍历
//        Iterator<Map.Entry<String, String>> it = entry.iterator();
//        while(it.hasNext()){
//            Map.Entry<String, String> next = it.next();
//            System.out.println(next.getKey()+"="+next.getValue());
//        }
/*
输出:
{令狐冲=东方不败, 杨过=小龙女, 郭靖=黄蓉}
令狐冲=东方不败
杨过=小龙女
郭靖=黄蓉
令狐冲=东方不败
杨过=小龙女
郭靖=黄蓉
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值