第十五节 集合 (一) Collection + 泛型

1. 什么是集合 ?

  1. 可以把它比作一种容器,也是用来存储数据的。可以存储,不同类型的数据。
    • 不能存储基本类型。 , 可以存储基本类型的包装类。
    • 集合的长度不是固定的,是可以改变的,随着元素的增长而增长。
    • 删除,插入,非常方便。
  2. 它是怎么产生的!? 从之前学过的知识点分析,肯定是为了解决一些情况而产生的。
    • 如,在同一个集合中存储不同的数据类型。(注意:但是一般不会这么干!)
  3. 数组和现在的集合对比区别!? 还记得数组的特点么!?

1.2. Collection

1.2.1 集合的关系“全家福”

  1. 集合,在语言设计上是 面向对象的,通过 继承,实现 等设计思想来完成。
  2. 在集合上也是找到相同关系的子类进行向上抽取共同的方法,使结构变得简单,使用不同的子类来处理不同的场景。

在这里插入图片描述

  • 清爽的简化过程图:

在这里插入图片描述

1.2.2 Collenction结构

  1. API原话直译第一行 :集合表示一组被称为其元素的对象。

    • 一些集合允许重复元素,而其他集合不允许。 JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List 。 该界面通常用于传递集合,并在需要最大的通用性的情况下对其进行操作。
  2. 结构介绍:

		1.Collenction 接口: 
			-- 1.1 List 接口: 数据有序 (有下标), 可以重复。
				--  ArrayList  实现子类:
				--  LinkedList 实现子类:
			-- 1.2 Set 接口: 数据无序 (无下标),不可以重复。
				--  HashSet 实现子类:
				-- 	TreeSet 实现子类:
		2. Map 接口:键值对存数据。
			-- HashMap3. Collections  注意: 加了s的就是工具类。 

1.2.3 Collection 接口中方法介绍

  1. 学习共性方法,java.util.collection包下,了解之后在学习子类中特有的方法。
方法主要作用
boolean add(E e)添加元素
boolean addAll(Collection c)将指定集合中的所有元素添加到另一个集合。
boolean contains(Object o)如果此 collection 包含指定的元素,则返回 true。
boolean isEmpty()如果此 collection 没有元素,就是看集合是否为空,为空则返回 true。
int size()返回此 collection 中的元素数
Objec[] toArray()返回对象数组
boolean remove(Object o)从此 collection 中移除指定元素的单个实例
boolean removeAll(C c)集合之间的操作,将包含集合中的元素从集合中去除
void clear()从此集合中删除所有元素(可选操作)。 此方法返回后,集合将为空
Iterator< E > iterator()返回在此 collection 的元素上进行迭代的迭代器。

1.3 练习: Collection 中常用方法的使用

  1. java.util.conllection;包下,注意别导错包,以及Collection中,常用方法的使用。
    • Iterator< E > iterator(); 迭代器 的使用。
public class Test_Collection {
    public static void main(String[] args) {
        /* 怎么测试呢!?
            1.创建对象
            2.测试方法
            3.查看结果
         */
        Collection c = new ArrayList(); // 接口不能new 只能用实现类 ArrayList();
        //1向集合中添加元素。add(E e)这个E是泛型的意思。可以固定类型。
        c.add("老天师");
        c.add("武当王也");
        c.add(18);
        c.add('男');
        System.out.println(c); //直接可以查看结果。

        //1.1 clear() :清除集合里的所有元素。
        /*
            c.clear();
            System.out.println(c); //返回空了。
         */
        //1.2 contains() :指的是该集合是否包含指定元数,返回类型 boolean类型。
        System.out.println(c.contains("武当王也")); //true

        //1.3 hashcode(): 返回集合在内存中的哈希码值
        System.out.println(c.hashCode());

        //1.4 isEmpty():判断集合是否为空,为空则true
        System.out.println(c.isEmpty());

        //1.5 remove() : 移除集合中指定元数。
        System.out.println(c.remove("武当王也"));
        System.out.println(c);

        //1.6 size() : 返回集合中元数个数。
        System.out.println(c.size());

        //1.7 toArray() :集合返回数组对象返回的是object类型!
        Object[] objects = c.toArray();
        System.out.println(Arrays.toString(objects));

        System.out.println("--------------------华丽分割线--------------------");

        //2 <E>指的是固定类型。 一种约束。而且集合中只能添加引用类型。
        Collection<Integer> c2 = new ArrayList();
        //2.1 c2.add("王也"); //报错。 只能添加int类型的包装类Interger引用类型。
        c2.add(1949);
        c2.add(10);
        c2.add(1);



        /*测试集合与集合之间的操作*/
        //2.1 addAll(C c) :将后面集合添加到前面集合中。
        System.out.println(c.addAll(c2));
        System.out.println(c);
        System.out.println(c2);

        //2.1.1集合是需要指定泛型的, 如果不指定类型,则可以添加如果指定则不可以。如String 和 Interger不可以相互添加。
        Collection<String> c3 = new ArrayList();
        c3.add("老天师");
        // System.out.println(c2.addAll(c3)); //报错


        //2.2 containsAll(); 前面的集合包含后面集合 包含则返回true;
        System.out.println("containsAll: "+c.containsAll(c3));

        //2.3 removeAll(); 将集合后面的所包含的元数移除。
//        System.out.println("removeAll:"+c.removeAll(c3));
//        System.out.println(c);// [老天师] 已经被移除。

        //2.4 retainAll()只保留包含集合的相同的元素。
        System.out.println(c.retainAll(c3));
        System.out.println(c);


        /*
            3.重点: 迭代器 iterator(); 要想操作集合中的元素,就需要遍历\循环\迭代。
                    拿c2 集合做实验. 注意以下两个方法:
                    1.首先要获取结合的迭代器。
                    2.hasNext(); 如果集合有元素就返回  true;
                    3.next(); 返回迭代的元素。
         */

        //3.1 获取集合的迭代器
        Iterator<Integer> iterator = c2.iterator();
        //3.2 循环判断是否有下一个元素,通常使用while循环
        while (iterator.hasNext()){
            //3.3 如果有元素,就获取当前迭代的元素。
            Integer next = iterator.next();
            System.out.println(next);//输出
        }
    }
}

输出结果:

[老天师, 武当王也, 18,]
true
986602119
false
true
[老天师, 18,]
3
[老天师, 18,]
--------------------华丽分割线--------------------
true
[老天师, 18,, 1949, 10, 1]
[1949, 10, 1]
containsAll: true
true
[老天师]
1949
10
1
  • 为了方便理解,引入一个知识点: 泛型,通常和集合一起使用。

2 泛型

2.1 什么是泛型 ?

  1. 什么是泛型!? 其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 在程序 ‘编译期’ 间就会约束类型,相当于在编译器提供了一个安全检查机制。
    • 泛型生活中的例子<T>。如:班主任:她在门口看着每一个进班级的学生,<我们班学生>是这个班就让进(相当于提前指定了类型), 不是就不让进。
    • 要吃饭自然就少不了碗,但是没有规定碗只能盛饭,除了盛饭它还能干其他的,编写代码人员不关心碗盛什么,具体要盛什么由使用者来决定,
  2. 泛型(Generics)通常跟集合一起使用
  3. 集合特点:就是可以接受任意类型的元素,但是在实际使用过程中会经常遇到类型转换问题,这样就会存在隐患。 所以java提供了泛型 解决了安全问题。
    • 如:ClassCastException 类型转换不兼容异常。

2.1.1 泛型的安全问题

  1. 这个时候用的 <T> 也是用的多态的思想,因为我们不知道子类会传什么对象过来,同时这样写也增加了子类的扩展性。

  2. 子类就可以像下面这样根据自己的需要传入对象:

    • 如果没有泛型约束,就会经常发生类型强制转 换问题。
    public static void main(String[] args) {
            /*1.没有泛型约束
                   相当于存入的是Object类型
                   		如果使用就需要强制转换为Integer
             */
            Collection c = new ArrayList();
            c.add(18);
            c.add("20");//添加  String类型的 20
    
            Iterator iterator = c.iterator();
            while(iterator.hasNext()){
                Object next = iterator.next();//如果使用需要转换类型
                //需要使用时
                Integer i = (Integer)next;
                System.out.println(i);//发生转换错误 ClassCastException
            }
    
            /*2.有泛型约束,取出结果不需要强制转换,
                   根据约束存储类型一致。
             */
            Collection<Integer> c2 = new ArrayList();
            //c2.add("20"); //只能添加 integer类型
            c2.add(18);
    
            Iterator<Integer> iterator2 = c2.iterator();
            while(iterator2.hasNext()){
                Integer next = iterator2.next();//直接就是Integer类型
                System.out.println(next);
            }
        }
    

在这里插入图片描述

2.1.2 作用

  1. 通过泛型的语法定义,约束集合元素的类型,进行安全检查,把错误显示在编译期,减少在运行期间出错。
  2. 泛型可以提升程序代码的可读性,代码的通用性。

2.2 泛型格式

  1. Eclipse 是自动开启的, 但是IDEA 泛型设置默认不检查,需要自己开启。
    • 第一个检查勾选的话是右边不检查约束。 在JDK 1.8之后第二个尖括号可以不写。
      在这里插入图片描述
      在这里插入图片描述
public class Test_Generics {
    public static void main(String[] args) {
        /*
        1.当我们创建一个集合时,就会有这样的警告,
        // ArrayList arrayList = new ArrayList();
                原因是:泛型警告,查看底层发现有泛型约束。这个<E>
           public class ArrayList<E> extends AbstractList<E>
                 implements List<E>, RandomAccess, Cloneable, java.io.Serializable
         */
         
        ArrayList<String> arrayList = new ArrayList();//在jdk1.8以后就不需要右边加约束了。也可以自动推断类型。

        //2.约束的作用在于什么地方呢!?声明时需要指定传入参数类型,编译器在编译阶段会自动校验。
        //arrayList.add(1949);//在编译期间就会提示错误。添加一个Interger类型或报错!?因为<String>约束里是String类型的。
        arrayList.add("1949-10-1");//添加String类型就不会报错。
    }
}

2.2.1 泛型声明位置

  1. 声明时,需要指定传入参数类型,编译器在编译阶段会自动校验。
名称作用
EElement 在集合中使用,因为集合中存放的是元素
TType(表示Java 类,包括基本的类和我们自定义的类)
KKey(表示键,比如Map中的key)
VValue(表示值)
NNumber(表示数值类型)
(表示不确定的java类型)
  1. 以使用在 接口,类,方法,上使用。
    • 提示:参考Collection 集合源码。
    • 泛型在类上, 泛型在方法上区别。
    public class Test<E> { //泛型定义在类上,在整个类都有效
    
        public void add(E e){ // 跟类的保持一致。
            System.out.println(e);
        }
    	
    	//泛型在方法上,跟方法保持一致,不受类的影响。
    	public  static <T> void  show(T t){ 
        System.out.println(t);
    	
    	 }
    
        public static void main(String[] args) {
            Test<Integer> s = new Test();
            s.add(12); //添加的就是Integer类型
    
            Test<String> i = new Test();
            i.add("12");//添加的就是 String类型
    
            Test t = new Test(); //无约束
            t.add(1.1);//没有约束 ,添加的就是Objetc类型
    
    		show("我叫张三");
        	show(12);
        }
    }
    

2.3. 课堂练习

2.3.1 练习:forech 使用

  1. foreach增强型的使用,与for()循环比较。
    • 遍历数组,和 遍历集合。
	public class Test2_Generics {
	    public static void main(String[] args) {
	
	        /*1. foreach 遍历效率高,缺点无法控制打印步长。
	        	          不需要控制变量长度时,选择foreach,效率高。
	            语法格式: for(数据类型 遍历名称:遍历对象){}
	         */
	        //1.泛型和数组很像。
	        String[] arr = new String[5];
	        arr[0] ="1";
	        arr[3] ="10";
	        //arr[4] =20; //这样是不允许的。
	
	        //1.1 数组遍历方式
	        for (int i = 0; i <arr.length ; i++) {
	            System.out.println(arr[i]);//能控制打印哪个元数
	        }
	        //1.2 foreach 遍历
	        for (String s: arr) {
	            if (s!=null){//控制不打印无效元数
	                System.out.println(s); //直接全部打印
	            }
	        }
	
	        /*2. 集合遍历
	         */
	        Collection c = new ArrayList();//没有泛型约束
	        c.add(1);
	        c.add("你好");
	
	        //2.1 遍历,因为没有约束 添加的就是Object类型
	        for (Object o : c) {
	            System.out.println(o);
	        }
	    }
	}

2.3.2 练习:打印方法–数组

  1. 将泛型定义在方法上。
    • 泛型增强的通用性,foreach(E[ ] e)
 public static void main(String[] args) {

        /*1.打印数组
         */
        String[] s_name ={"张三","李四","王五"};
        println_String(s_name);

        //1.1 打印double int 方法
        Double[] d_salary = {18.0,28.0,38.0,48.0};
        Integer[] i_age = {18,28,38,48};
        // println_String(i_age); //为什么不行?怎么办,,这样又写很多个方法

        /*2.泛型的使用
         */

        println_E(d_salary);
        println_E(i_age);


    }

    /**
     * 泛型定义在方法上
     * @param e
     */
    private static <E>void println_E(E[] e) {
        //泛型通配符使用
        for (E res:e) {
            System.out.println(res);
        }
    }

    /**
     * 打印数组的方法
     * @param s_name
     */
    private static void println_String(String[] s_name) {
        for (String s:s_name) {
            System.out.println(s);
        }
    }

2.4 知识扩展: 泛型的上下界通配符

2.4.1 无界限

  1. 通配符有很多 T 就可以了 为什么还有
    • <T>代表的声明的意思, <?> 具体是怎么使用。
    • 主要是为了 可读性。
public static void main(String[] args) {

        //1.无界限通配符,打印集合
        Collection<Integer> c = new ArrayList();
        c.add(18);
        c.add(18);
        Collection<String> c2 = new ArrayList();
        c2.add("你好");
        c2.add("中国");

        //2. 可以任意打印
        print(c);
        print(c2);
    }

    /**
     * 无界限通配符<?>
     * 打印集合
     * @param c
     */
    private static void print(Collection<?> c) {
        Iterator<?> iterator = c.iterator();
        while(iterator.hasNext()){
            Object next = iterator.next(); //默认就是Object
            System.out.println(next);
        }
    }

2.4.2 上界通配符

  1. 类型名称 <? extends 类 > 对象名称
    • 只能接受本类 或其子类。
public class Test {
    public static void main(String[] args) {

        Collection<Girl> c  = new ArrayList();
        Collection<Boy> c2  = new ArrayList();
        Collection<Person> c3  = new ArrayList();
        Collection<Object> c4  = new ArrayList();
        //print(c4); //Object 不可以
    }

    //1.上界通配符,即上限
    public static void print(Collection<? extends Person> c){
        System.out.println(c);
    }
}

class Person{}
class Girl extends Person{} //继承父类
class Boy extends Person{} // 继承父类

2.4.3 下界通配符

  1. 类型名称 <? super 类 > 对象名称
    • 只能接收本类型 及其父类。
public class Test {
    public static void main(String[] args) {

        Collection<Girl> c  = new ArrayList();
        Collection<Boy> c2  = new ArrayList();
        Collection<Person> c3  = new ArrayList();
        Collection<Object> c4  = new ArrayList();
        // print(c); // 子类不可以 
        // print(c2); // 子类不可以 
        print(c4); // 父类可以
    }

    //1.下界通配符,即下限。
    public static void print(Collection<? super Person> c){
        System.out.println(c);
    }
}

class Person{}
class Girl extends Person{} //继承父类
class Boy extends Person{} // 继承父类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
回答: Java集合框架中的Map是一种键值对的数据结构,可以存储一组具有唯一键和对应值的元素。使用可以在编译时进行类检查,确保集合中只能存储指定类的元素,提高代码的可读性和安全性。 在引用中的示例代码中,List<String>定义了一个只能存储字符串类元素的列表。在引用中的示例代码中,Collection<String>和Collection<Integer>分别定义了只能存储字符串类和整数类元素的集合。使用通配符可以增加集合的灵活性。比如在coll.removeAll(c)方法中,传入的Collection对象的可以是任意类。另外,还可以应用于Map集合,如引用中的示例代码中,Set<Map.Entry<String,String>>定义了只能存储键值对类为String的元素的集合。 综上所述,Java集合框架中的Map和可以一起使用,通过可以指定集合中存储的元素类,增加代码的可读性和类安全性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [java基础中的--------Map+](https://blog.csdn.net/liutaiwu/article/details/107915445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴琼老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值