新手小白学JAVA 泛型 Collection List Set

Posted 程序媛 泡泡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新手小白学JAVA 泛型 Collection List Set相关的知识,希望对你有一定的参考价值。

集合

我们接下来要学习的内容是Java基础中一个很重要的部分:集合
为了更好的理解集合,我们需要首先引入一个概念:泛型

1 泛型

1.1 概念

我们可以观察一下,下面的代码中有什么元素是我们之前没见过的呢?
在这里插入图片描述
其实就是< ? >的部分,它就是泛型
泛型是(Generics)JDK1.5 的一个新特性,通常用来和集合对象一起使用
泛型概念非常重要,它是程序的增强器,它是目前主流的开发方式

1.2 作用

那泛型有什么作用呢?
我们可以把泛型理解成一个“语法糖”,本质上就是编译器为了提供更好的可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓“泛型”的概念的。是不有点神奇,不知所云,别着急等我讲完你就清楚了。

我们可以通过泛型的语法定义<>,来约束集合中元素的类型,编译器可以在编译期根据泛型约束提供一定的类型安全检查,这样可以避免程序运行时才暴露BUG,代码的通用性也会更强
泛型可以提升程序代码的可读性,但是它只是一个“语法糖”(编译后这样的部分会被删除,不出现在最终的源码中),所以不会影响JVM后续运行时的性能.

1.3 泛型示例

示例1 : 我们创建一个ArrayList,看到eclipse发出黄线警告,这是为什么呢?
原因:ArrayList定义时使用了泛型,在声明时需要指定具体的类型 在这里插入图片描述在这里插入图片描述
我们把这个”<>”的方式称之为泛型,那么泛型有什么样的作用呢?就是在编译阶段检查传入的参数是否正确
在这里插入图片描述有了泛型,我们可以看到要求存放的是String类型,而测试时存放的是int类型的100,所以编译器报错:
类型List的add方法要求添加的类型为String类型,int类型不匹配,不能正确存入

1.4 泛型声明

泛型可以在接口 类 方法上使用
在这里插入图片描述
在方法的返回值前声明了一个,表示后面出现的E是泛型,而不是普通的java变量

1.5 常用名称

在这里插入图片描述

1.6 练习:泛型测试

创建包: cn.tedu. generic
创建类: TestGeneric1.java

package cn.tedu.generic;

import java.util.ArrayList;
import java.util.List;

/**本类用于测试泛型的优点*/
public class TestGeneric1 {
	public static void main(String[] args) {
		/**1.泛型是怎么来的?--想要模拟数组的数据类型检查*/
		String[] a = new String[5];//创建一个用来存放String类型数据的数组,长度为5
		a[2] = "泡泡";
		a[4] = "涛涛";
		//数组的好处:在编译时期检查数据的类型,如果不是要求的类型会在编译器就报错
		//a[0] = 1;
		//a[1] = 8.8;
		//a[3] = 'c';
		
		/**2.泛型通常会结合着集合一起使用*/
		List list = new ArrayList();//注意导包:java.util...
		//没有泛型,数据类型根本没有约束 -- 太自由!!!
		list.add("江江");
		list.add(1);
		list.add(8.8);
		list.add('a');
		System.out.println(list);//通过打印查看集合中的元素
		
		/**3.引入泛型--主要目的是想通过泛型来约束集合中元素的类型<?>*/
		/**4.泛型的好处:可以把报错的时机提前,在编译期就报错,而不是运行后抛出异常
		 * 在向集合中添加元素时,会先检查元素的数据类型,不是要求的类型就编译失败
		 * */
		List<String> list2 = new ArrayList<String>();//注意导包:java.util...
		list2.add("雷神");//约束了类型以后,只可以传String参数
		//list2.add(1);
		//list2.add(8.8);
		//list2.add('d');
		
		/**5.<type>--type的值应该如何写?
		 * 需要查看要存放的数据类型是什么,根据类型进行定义
		 * 但是type必须是引用类型,不是基本类型
		 */
		//List<int> list3 = new ArrayList<int>();//注意导包:java.util...
		List<Integer> list3 = new ArrayList<Integer>();//注意导包:java.util...
		list3.add(100);
		list3.add(200);
		System.out.println(list3);
	}
}

1.7 练习:泛型测试2

创建包: cn.tedu. generic
创建类: TestGeneric2.java

package cn.tedu.generic;
/**本类用来测试泛型的优点2*/
public class TestGeneric2 {
	public static void main(String[] args) {
		//需求:打印指定数组中的所有元素
		Integer[] a = {1,2,3,4,5,6,7,8,9,10};
		print(a);
		
		String[] b = {"大哥","二哥","三哥","四哥","五哥","六哥","小弟"};
		print(b);
		
		Double[] c = {6.0,6.6,6.66,6.666,6.6666};
		print(c);
	}
	/**1.泛型可以实现通用代码的编写,使用E表示元素的类型是Element类型 -- 可以理解成神似多态*/
	/**2.泛型的语法要求:如果在方法上使用泛型,必须两处同时出现,一个是传入参数的类型,一个是返回值前的泛型类型,表示这是一个泛型*/
	private static <E> void print(E[] e) {
		for(E d :e) {
			System.out.println(d);
		}
	}

//	public static void print(Double[] c) {
//		for(Double d : c) {
//			System.out.println(d);
//		}
//	}
//
//	public static void print(String[] b) {
//		for(String s : b) {
//			System.out.println(s);
//		}
//	}
//
//	public static void print(Integer[] a) {
//		//使用普通循环遍历数组比较复杂,引入高效for循环
//		//普通循环的好处是可以控制循环的步长(怎么变化)
//		for (int i = 0; i < a.length; i=i+2) {
//			System.out.println(a[i]);
//		}
//		/**
//		 * 高效for/foreach循环--如果只是单纯的从头到尾的遍历,使用增强for循环
//		 * 好处:比普通的for循环写法简便,而且效率高
//		 * 坏处:没有办法按照下标来操作值,只能从头到尾依次遍历
//		 * 语法:for(1 2 : 3){代码块} 3是要遍历的数据  1是遍历后得到的数据的类型 2是遍历起的数据名
//		 */
//		for(Integer i : a) {
//			System.out.print(i);
//		}
//	}
}

2 Collection接口

2.1 集合前言

Java语言的java.util包中提供了一些集合类,这些集合类又称之为容器
提到容器不难想到数组,集合类与数组最主要的不同之处是,数组的长度是固定的,集合的长度是可变的,而数组的访问方式比较单一,插入/删除等操作比较繁琐,而集合的访问方式比较灵活
在这里插入图片描述
常用的集合类有List集合,Set集合,Map集合,其中List集合与Set集合继承了Collection接口,各个接口还提供了不同的实现类.
在这里插入图片描述

2.2 集合概念

集合的英文名称是Collection,是用来存放对象的数据结构,而且长度可变,可以存放不同类型的对象,并且还提供了一组操作成批对象的方法.Collection接口层次结构 中的根接口,接口不能直接使用,但是该接口提供了添加元素/删除元素/管理元素的父接口公共方法.
由于List接口与Set接口都继承了Collection接口,因此这些方法对于List集合和Set集合是通用的.

2.3 集合的继承结构

Collection接口
List 接口【数据有下标,有序,可重复】
ArrayList子类
LinkedList子类
Set 接口【数据无下标,无序,不可重复】
HashSet子类
Map 接口【键值对的方式寸数据】
HashMap子类

2.4 Collection方法速查表

在这里插入图片描述

2.4 练习:Collection接口测试

创建包: cn.tedu.collection
创建类: TestCollection.java

package cn.tedu.colletion;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**本类用来测试Collection接口*/
public class TestColletion {
	public static void main(String[] args) {
		//1.创建Collection接口相关对象
		//Collection c = new Collection();//报错,因为Collection是接口不能实例化new 
		/**1.<Integer>是泛型,用来约束集合中的元素的类型,只能写引用类型,不能是基本类型*/
		Collection<Integer> c = new ArrayList<Integer>();
		
		//2.1测试常用方法--对于单个集合的方法
		c.add(100);//向集合中添加元素
		c.add(200);//向集合中添加元素
		c.add(300);//向集合中添加元素
		c.add(400);//向集合中添加元素
		c.add(500);//向集合中添加元素
		System.out.println(c);//直接打印查看集合中的元素
		
		//c.clear();//清空集合中的元素
		//System.out.println(c);
		
		System.out.println( c.contains(300) );//true,判断集合中是否包含元素300
		System.out.println( c.hashCode() );//127240651,返回集合对应的哈希码值
		System.out.println( c.isEmpty() );//false,判断集合是否为空
		System.out.println( c.remove(100) );//true,移出集合中的元素100,移出成功返回true
		System.out.println( c );//[200, 300, 400, 500],100被成功移除
		System.out.println( c.size() );//4,获取集合的元素个数/类似数组长度
		System.out.println( c.equals(200) );//false,判断是否与100相等
		
		/**接返回值类型快捷键:Shift+alt+L*/
		Object[] array = c.toArray();//把集合中的元素放入数组
		System.out.println(Arrays.toString(array));//使用数组的工具类查看数组中的元素内容
		
		//2.2测试常用方法--集合间的操作
		Collection<Integer> c2 = new ArrayList<Integer>();
		
		c2.add(2);//给c2集合添加元素
		c2.add(4);//给c2集合添加元素
		c2.add(6);//给c2集合添加元素
		System.out.println(c2);//[2, 4, 6],直接打印查看c2集合的内容
		
		c.addAll(c2);//把c2集合添加到c集合中
		System.out.println(c);//[200, 300, 400, 500, 2, 4, 6],追加操作
		System.out.println(c.contains(c2));//false
		System.out.println(c.containsAll(c2));//true,查看c集合是否包含c2集合中的所有元素
		
		System.out.println(c.removeAll(c2));//true,删除c集合中属于c2集合的所有元素
		System.out.println(c);//[200, 300, 400, 500],查看c集合删除c2集合后的结果,正确删除
		//System.out.println(c.retainAll(c2));//true,删除c集合
		//System.out.println(c);//[]
		
		//2.3 用来遍历/迭代集合中的元素 Iterator<E> iterator()
		/**
		 * 1.如何获取迭代器 c.iterator()
		 * 2.判断集合是否有下个元素 it.hasNext()
		 * 3.获取当前迭代到的元素 it.next()
		 */
		Iterator<Integer> it = c.iterator();
		//通过iterator迭代器,循环获取集合中的元素
		while(it.hasNext()) {
			//hasNext()用来判断集合中是否有下个元素,有就返回true,继续循环取值
			Integer num = it.next();//next()用来获取迭代到的元素
			System.out.println(num);
		}
	
	}
}

3 List接口

3.1 概述

有序的colletion(也称为序列).此接口的用户可以对列表中的每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)来访问元素,并搜索列表中的元素.

3.2 特点

  1. 元素都有下标
  2. 数据是有序的
  3. 允许存放重复的元素

3.3 List方法速查表

在这里插入图片描述

3.4 练习:List接口测试

创建包: cn.tedu.collection
创建类: TestList.java

package cn.tedu.colletion;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**本类用于测试List接口*/
public class TestList {
	public static void main(String[] args) {
		//1.创建List接口对象,注意此处创建的多态对象,List是接口,不能直接实例化
		List<String> list = new ArrayList<String>();//注意导包:java.util...导包快捷键:Ctrl+Shift+O
		
		//2.测试继承自Colletion接口的方法
		list.add("大力娃");//向集合中添加元素
		list.add("千顺娃");
		list.add("头铁娃");
		list.add("喷火娃");
		list.add("喷水娃");
		list.add("隐身娃");
		list.add("小紫娃");
		System.out.println(list);//查看集合中的所有元素
		//list.clear();//清空集合
		//System.out.println(list);//[],集合已清空
		
		System.out.println("**********我是一个无情的分界线**************");
		System.out.println( list.contains("大力娃"));//判断是否包含元素"大哥"
		System.out.println( list.equals("头铁娃"));//判断list对象是否与"二哥"相等
		System.out.println( list.hashCode());//获取集合的哈希码值
		System.out.println( list.isEmpty());//判断集合是否为空
		System.out.println( list.remove("喷水娃"));//移除集合中的元素"五哥"
		System.out.println( list );//查看集合中的内容
		System.out.println( list.size());//获取集合的元素个数,类似于数组的长度
		//将集合中的元素存入数组中,打印需要使用数组的工具类Arrays
		System.out.println( Arrays.toString(list.toArray()));//[大哥, 二哥, 三哥, 四哥, 六哥, 七弟]
		
		//3.List接口的特有方法  -- 都是可以根据索引来操作的方式
		list.add("小蝴蝶");//追加在最后
		System.out.println(list);
		list.add(1,"蝎子精");//在指定索引处添加指定的元素
		System.out.println(list);
		System.out.println(list.get(2));//获取指定下标对应的元素
		list.add(3,"小蝴蝶");
		System.out.println(list);
		System.out.println(list.indexOf("小蝴蝶"));//获取指定元素第一次出现的索引
		System.out.println(list.lastIndexOf("小蝴蝶"));//获取指定元素最后一次出现的索引
		System.out.println(list.remove(6));//移除指定索引的元素
		System.out.println(list.set(0, "妖精蛇"));//重置指定索引处位置的值
		System.out.println(list);
		List<String> subList = list.subList(2, 6);//截取子串,[2,6)含头不含尾
		System.out.println(subList);
		
		//4.集合间的操作
		List<String> list2 = new ArrayList<String>();
		list2.add("1");
		list2.add("2");
		list2.add("3");
		System.out.println( list.addAll(list2) );//把list2集合添加到list集合中
		System.out.println( list.addAll(1,list2) );//把list2集合添加到list集合的指定位置处
		System.out.println( list );
		System.out.println( list.contains(list2) );//判断list集合是否有一个元素是list2
		System.out.println( list.containsAll(list2) );//判断list集合是否包含list2集合中的所有元素
		System.out.println( list.removeAll(list2) );//删除list集合中list2集合中的所有元素
		System.out.println( list);
	}
}

3.5 练习:List接口测试2

创建包: cn.tedu.collection
创建类: TestList2.java

package cn.tedu.colletion;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**本类用于进一步测试List接口,注意导包:java.util*/
public class TestList2 {
	public static void main(String[] args) {
		//1.创建List接口对象 导包快捷键:Ctrl+Shift+O
		List<String> list = new ArrayList<String>();
		
		//2.向集合中添加元素
		list.add("喜羊羊");
		list.add("美羊羊");
		list.add("懒羊羊");
		list.add("沸羊羊");
		list.add("小肥羊");
		list.add("红太阳");
		
		//3.测试集合的迭代
		/**
		 * 集合迭代的方式:
		 * 1.for循环
		 * 2.增强for循环
		 * 3.iterator
		 * 4.listIterator
		 * */
		//方式一:因为List集合是有序的,元素有下标,所以可以根据下标进行遍历
		//从何开始:0 到哪结束:list.size() 如何变化:i++
		for(int i = 0 ; i< list.size() ; i++) {
			//根据对应的下标来获取集合对应位置上的元素
			String s = list.get(i);
			System.out.println(s);
		}
		System.out.println("***********我是一个无情的分割线1***************");
		
		//方式二:普通for循环遍历效率低,可以通过foreach提高遍历效率
		//好处:语法简洁效率高 坏处:不能按照下标来处理数据
		//格式:for(1 2 : 3){循环体} 3是要遍历的数据 1和2是遍历得到的单个数据的类型 和 名字
		for(String s : list) {//s就是本次循环/遍历得到的集合中的元素
			System.out.println(s);
		新手小白学JAVA 抽象类

新手小白学JAVA 学习路径 知识体系

新手小白学JAVA 异常

java容器--------泛型

新手小白学JAVA IDEA下载使用手册

新手小白学java 编码转换流 OutputStreamWriter InputStreamReader