java基础——第九章:java基础(集合框架、泛型)

本章概述:

第一部分:集合框架

Collection

 

List

Set

Map

 

第二部分:集合框架工具类、高级for

第三部分:泛型

 

 

 

 

 

第一部分:集合框架

一、集合框架的特点及与数组的区别

存储对象的容器,方便对多对象进行操作

数组的长度固定,集合不固定

集合可以存储不同类型的对象

集合内添加的是元素的引用

 

二、Collection接口:

Collection的共性方法:

add(E e)  添加元素

addAll(Collection<? extends E> c)  添加指定集合中的所有元素

 

remove(Object o)  移出元素

removeAll(Collection<?> c)  移出指定集合中包含的元素

 

retainAll(Collection<?> c)   移出指定集合中没有包含的元素

clear()   清空集合中的元素

contains(Object o)   判断元素是否存在

containsAll(Collection<?> c)   判断指定集合中的元素是否存在

equals(Object o)  比较集合与指定对象是否相等

hashCode()  返回对象的哈希码值

isEmpty()  判断集合中的元素是否为空

size()  获取集合的长度(元素个数)

toArray()   将集合转换成数组

toArray(T[] a)  将集合转换成指定运行时类型的数组

iterator()  返回该集合的迭代器

 

迭代器是集合接口的内部类,取出的动作是集合内部的事情,用方法不足以描述,所以定义成内部类, 不同的容器数据结构不同,取出方式不同,但取出都有共性内容(判断和取出)所以抽象成接口

1、List

List集合的特点:

元素是有序的,元素可以重复,以为该集合体系有索引

凡是可以操作角标的方法都是该体系特有的方法

List的共性方法:

 

add(index,element  将元素添加到指定索引处

addAll(index,Collection)  将某个指定集合中的全部元素从指定索引处开始添加

remove(index)  移出指定索引处的元素

set(index,element)  修改指定索引处的元素为指定新元素

get(index)  获取某一指定索引处的元素引用

indexOf  在集合中查找元素

lastIndexOf  从集合后面开始查找指定元素

subList(start,end)  获取子集  获取从指定位置到另一指定位置的处的全部子集元素

listIterator  返回List集合的特有比较器(可以使用角标操作数据)

 

(1)ArrayList:

1)ArrayList是数组结构的:

数组结构集合的特点是查询快、增删慢

2)ArrayList是线程不同步的

3)ArrayList的长度可变原理:

初始化时new一个长度为10的ArrayList集合,当存储的元素大于10个时,又重新new一个长度比原来增加一半的ArrayList集合,将原有数据迁移过去

4)ArrayList的方法:

和List接口的方法基本一致,可以参照List中的方法

 

代码示例:

 

/*
需求:ArrayList代码示例
*/

import java.util.*;

//定义类
class  ArrayListDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个ArrayList集合
		List list = new ArrayList();

		//给集合添加元素
		list.add("ZhangSan");
		list.add("LiSi");
		list.add(1,"WangWu");  //将指定元素添加到指定索引位置
		
		//调用自定义方法遍历集合
		reads(list);

		list.set(0,"ZhaoLiu");  //将索引0处的元素修改为新元素

		//修改后
		System.out.println("修改后");
		reads(list);

		//查找元素
		int index = list.indexOf("WangWu");  //查找“WangWu”
		list.remove(index);  //移出“WangWu”

		System.out.println("移出“WangWu”后");
		reads(list);  //移出后


	}
	//定义专门用于遍历集合并打印的函数,简化代码的书写
	public static void reads(List list)
	{
		//遍历集合元素
		for (int i = 0;i<list.size() ;i++ )
		{
			System.out.println(list.get(i));
		}
	}
}
 

 

 

练习:取出ArrayList中的重复元素

(2)LinkedList

1)链表结构:增加、修改快,查询慢

2)线程不同步

3)方法:

addFirst  在集合的开头添加元素,无返回

offerFrist 在集合的开头处插入元素,返回boolean

addLast  在集合的末尾添加元素

getFirst  获取集合开头处的元素

peekFrist  获取但不移除此列表的第一个元素,如果列表为空,则返回null

getLast  获取列表最后一个元素

removeFirst  移出此列表的第一个元素

pollFrist   获取并移除此列表的第一个元素

removeLast  移出此列表的最后一个元素

 

代码示例:

 

/*
需求:LinkedList代码示例
*/

//导入集合框架所在的包中的类
import java.util.*;

//定义类
class  LinkedDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个LinkedList集合
		LinkedList list = new LinkedList();

		//给集合添加元素
		list.add("ZhangSan");
		list.add("LiSi");
		list.add("WangWu");  
		list.add("ZhaoLiu");
		
		//调用自定义方法遍历集合
		reads(list);


		//用模拟堆栈的方法遍历集合
		System.out.println("先进后出");
		while(!list.isEmpty())
		{
			System.out.println(list.removeLast());
		}

		System.out.println("\r\n或者");
		//给集合添加元素
		list.addFirst("ZhangSan");
		list.addFirst("LiSi");
		list.addFirst("WangWu");  
		list.addFirst("ZhaoLiu");
		
		//调用自定义方法遍历集合
		reads(list);


		//用模拟堆栈的方法遍历集合
		System.out.println("先进后出");
		while(!list.isEmpty())
		{
			System.out.println(list.removeFirst());
		}

	}
	//定义专门用于遍历集合并打印的函数,简化代码的书写
	public static void reads(List list)
	{
		//遍历集合元素
		for (int i = 0;i<list.size() ;i++ )
		{
			System.out.println(list.get(i));
		}
	}
}
 

 

练习;模拟堆栈、队列

(3)Vector

和ArrayList的区别是Vector是线程同步的,当元素填满初始化的集合长度后,Vector会重新new一个原来长度2倍的Vector集合,一般情况下建议使用ArrayList,因为ArrayList效率高

2、Set

Set集合的特点:

元素是无序的(存入的顺序和取出的元素不一定一致,元素不可以重复

Set是Collection框架中的一员,拥有Collection中的共性方法,Set中没有定义特有方法

(1)HashSet

底层数据结构是哈希表

通过元素的两个方法保证元素的唯一性 如果hashCode相同就不调用equals(复写两个方法)

对于判断元素是否存在和删除元素,依赖的是元素的hashCode和equals方法

(2)TreeSet

底层数据结构是二叉树

可以对Set集合的元素进行排序

通过compareTo方法保证元素的唯一性和有序性

TreeSet排序的两种方式

让元素自身具备比较性

元素需要实现Comparable接口,覆盖compareTo方法 这种方法也成为元素的自然顺序,也叫默认顺序

在集合初始化时传入比较器对元素可比较

当元素不具备比较性或具备的比较性不是所需要的, 就定义比较器(Comparator比较器,方法compare、 equals)传给集合的构造函数

当两种排序方式都存在时,以比较器为主

 

代码示例:

 

/*
需求:Set代码示例
*/

//导入集合框架所在的包中的类
import java.util.*;

//定义类
class  SetDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个Set集合
		Set set = new TreeSet();

		//给集合添加元素
		set.add("ZhangSan");
		set.add("LiSi");
		set.add("WangWu");  
		set.add("ZhaoLiu");
		
		//获取集合的迭代器
		Iterator it = set.iterator();
		//用迭代器遍历集合
		while(it.hasNext())  //有没有下一个元素啊
		{
			//有则打印下一个元素
			System.out.println(it.next());
		}
	}
}

 

 

练习:按长度排序字符串

 

3、Map

1、Map集合特点:

Map集合存储的元素以键值对的形式存储,而且要保证键的唯一性

 

2、Map的共性方法:

put(K key, V value)   添加元素到该集合
putAll(Map<? extends K,? extends V> m)  添加指定Map集合中的所有元素到该集合
clear()    清空集合中的元素
remove(Object key)  移出指定元素
get(Object key)  返回指定键对应的值
keySet()   返回此集合的键集的Set视图
entrySet()   返回该集合的键值对映射关系的Set视图
size()   返回该集合的长度
values()   返回该集合所有值的Collection视图
containsKey(Object key)  判断集合中是否包含指定键
containsValue(Object value)  判断集合中是否包含指定值
isEmpty()    判断集合是否为空(是否有元素)
equals(Object o)  比较指定的对象与映射是否相等
hashCode()   返回此集合的哈希码值

 

(1)HashTable

哈希表数据结构

不可以有null键null值

是线程同步的

(2)HashMap

哈希表数据结构

可以有null键null值

是线程不同步的

(3)TreeMap

二叉树数据结构

可以给键排序

线程不同步

 

代码示例:

 

/*
需求:Map代码示例
*/

//导入集合框架所在的包中的类
import java.util.*;

//定义类
class  MapDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个HashMap集合
		Map map = new HashMap();

		//给集合添加元素
		map.put("ZhangSan",33);
		map.put("LiSi",22);
		map.put("WangWu",11);  
		map.put("ZhaoLiu",23);
		map.put("null",23);
		
		//获取map集合的键集Set视图
		Set set = map.entrySet();
		//获取集合的迭代器
		Iterator it = set.iterator();
		//用迭代器遍历集合
		while(it.hasNext())  //有没有下一个元素啊
		{
			//有则打印下一个元素(这里的元素就是键值对映射关系
			System.out.println(it.next());
		}
	}
}
 

 

练习:字母出现的次数

 

存储方式(数据结构)

为什么会出现这么多容器?因为每个容器对元素的存储方式不同(数据结构)

数组

链表

哈希表

二叉树

 

 

 

 

 

 

第二部分:集合框架工具类

1、Collections

(1)Collections是集合框架的工具类,定义了用于操作集合的静态方法

(2)方法:

max  取集合中的最大值

sort  给集合进行排序

binarySearch  折半查找,使用此方法前需要用Collections中的Sort方法对集合进行排序 

fill 替换指定集合中的全部元素

replaceAll(list,old,new)  将指定集合中的某一元素替换成新的元素

reverse  反转集合的排序

reverseOrder 返回一个强行逆转自然顺序的比较器

swap(List,int,int)  交换List中的两个指定元素的位置  

shuffle 随机置换元素

toArray 指定类型的数组长度不足,则新建一个集合长度的数组,指定数组长度比集合长度长,则多余部分用null填充

集合变数组为了限定集合

代码示例:

 

/*
需求:Collections代码示例
*/

import java.util.*;

//定义类
class  CollectionsDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个ArrayList集合
		List list = new ArrayList();

		//给集合添加元素
		list.add("345");
		list.add("456");
		list.add("123");
		list.add("345");
		list.add("234");
		
		//调用自定义方法遍历集合
		reads(list);

		System.out.println("最大值:"+Collections.max(list));

		//给集合进行排序
		Collections.sort(list);
		System.out.println("排序后:");
		reads(list);
		
		//折半查找
		System.out.println("查找“456”:"+Collections.binarySearch(list,"456"));
		
		//反转排序
		Collections.reverse(list);
		//反转后
		System.out.println("反转后");
		reads(list);

	}
	//定义专门用于遍历集合并打印的函数,简化代码的书写
	public static void reads(List list)
	{
		//遍历集合元素
		for (int i = 0;i<list.size() ;i++ )
		{
			System.out.println(list.get(i));
		}
	}
}
 

 

2、foreach(JDK1.5)

(1)用于对集合、数组进行遍历

(2)只能获取元素,不能对集合进行操作

(3)与传统for循环的区别

高级for有局限性,必须有被遍历的目标

在遍历数组的时候,建议还是使用传统for,因为传统for可以定义角标

被遍历的集合要定义泛型,否则元素类型要定义成Object

代码:

 

/*
需求:Foreach代码示例
*/

import java.util.*;

//定义类
class  ForeachDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个ArrayList集合
		List list = new ArrayList();

		//给集合添加元素
		list.add("345");
		list.add("456");
		list.add("123");
		list.add("345");
		list.add("234");
	
		//使用高级for遍历集合
		//集合中存入的是任意对象,所以接收要用Object
		//高级for中操作的是取出元素的引用,所以无法直接操作集合中的元素
		for (Object obj:list )
		{
			System.out.println(obj);
		}
	}
}
 

 

3、静态导入

只导入类中的静态成员

当类名重名时,要指定具体的包名

当方法重名时,要指定所属的对象或者类

import static 

 

 

 

 

 

第三部分:泛型

1、JDK1.5后出现的新特性,用于解决安全问题,解决类型安全问题

2、好处:

将运行时类型转换异常转移到了编译时期,方便程序员解决问题,让运行时异常减少,安全

避免了强制转换的麻烦

3、什么时候用:

只要看到<>就要定义泛型,<>是用来接收类型的,类型是引用数据类型

4、自定义泛型

什么时候定义泛型类?

当类中要操作引用数据类型不确定时,早期定义Object来完成扩展,现在定义泛型来扩展

静态方法不可以访问类上的泛型,如果静态方法要访问泛型,可以将泛型定义在方法上

定义泛型方法

泛型类定义的泛型在整个类中有效,如果被方法使用 那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了 为了让不同方法操作不同的类型,而且类型还不确定,那么可以将泛型定义在方法上

定义在返回类型前面

定义在接口上

接口在实现的时候可以明确泛型的具体类型,如果不明确,那么该类还是泛型类

? 泛型通配符

与T的区别:T代表具体类型,在类或方法上可以操作

泛型的弊端:

定义泛型就意味着还没有指定固定类型,就不可以使用固定类型的特有方法

 

泛型的限制:

 

泛型不可以定义多态

(因为定义父类但只能存父类中的一种子类,不合理)

可以有一种解决方法,? extends E (可以接收E或E的子类)或 ? super E(可以接收E或E的父类)

集合定义泛型示例:

 

/*
需求:泛型的简单示例
*/

import java.util.*;

//定义类
class  GenericDemo
{
	//主函数
	public static void main(String[] args)
	{
		//创建一个ArrayList集合,集合中定义了泛型,只可以存入String类型的元素
		List<String> list = new ArrayList<String>();

		//给集合添加元素
		list.add("345");
		list.add("456");
		list.add("123");
		list.add("345");
		list.add("234");
	
		//使用高级for遍历集合
		//定义泛型后可以直接接收String类型
		for (String s:list )
		{
			System.out.println(s);
		}
	}
}
 

 

 

 

本章总结

1、集合框架是一个对象存储容器的接口,它具有比数组更灵活的操作方式,可以实现比数组更广泛的应用,同一集合中可以存入任意对象,集合的长度是可变的,在集合中可以实现各种增删改查功能,集合框架中包含了多种不同的集合容器,其中有有序集合、无序集合、键值对集合、同步集合、非同步集合等等,方便在不同应用场景下使用不同的功能。

2、集合框架工具类是封装了大量静态方法提供给实现集合框架的更丰富的功能操作的一个类,可以使用工具类中的方法对集合进行多种操作。

3、高级for循环用于给集合和数组遍历集合,高级for的升级属于简化代码书写的升级,但是高级for中只能遍历不能直接对集合或数组中的元素进行操作,存在局限性,建议操作数组还是使用普通for循环,因为可以直接对元素进行操作。

4、泛型也是是JDK1.5出现的新特性,它可以定义集合中存入固定的类型或动态的限定类或方法中要操作的类型,将在运行时发生的类型转换异常转移到了编译时期,有助于程序员发现异常并及时修正。

5、静态导入就是只导入某些类中的静态成员。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值