java----集合类

集合类
一、集合类
疑问为什么会出现集合类?
:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储。集合就是存储对象最常用的一种方式。
疑问数组和集合类都是容器,有何不同?
:数组当然也可以存储对象,但长度是固定的。集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象
集合的特点:集合用于存储对象,长度是可变的,可以存储不同类型的对象。
集合框架

疑问为什么会出现这么多容器呢?
:因为每个容器对数据的存储方式都不同。这个存储方式称为——数据结构
import java.util.*;
class Demo
{
	public static void main(String args[]){
		//创建一个集合容器,使用Collection的子类ArrayList
		ArrayList al = new ArrayList();
		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//获取集合长度
		System.out.println(al.size());
	}
}

:出现了安全隐患提示,但是不影响运行。

集合的存储
import java.util.*;
class Person
{
	private String name;
	private int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public void show(){
		System.out.println("name = "+name+",age = "+age);
	}
}
class Demo{
	public static void main(String []args){
		Person p = new Person("zhangsan",20);
		ArrayList al = new ArrayList();
		al.add(p);
	}
}
分析:图解

分析
1.add方法的参数类型是Object,以便于接收任意类型对象。
2.集合中存储的都是对象的引用(地址)和数组一样。
删除元素
import java.util.*;
class Demo
{
	public static void main(String args[]){
		//创建一个集合容器,使用Collection的子类ArrayList
		ArrayList al = new ArrayList();
		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//删除前打印
		System.out.println("删除前:"+al);
		//删除元素
		al.remove("java02");
		//al.clear();
		System.out.println("删除后:"+al);
	}
}

判断元素
import java.util.*;
class Demo
{
	public static void main(String args[]){
		//创建一个集合容器,使用Collection的子类ArrayList
		ArrayList al = new ArrayList();
		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//判断
		System.out.println("java03是否存在:"+al.contains("java03"));
		System.out.println("集合是否为空:"+al.isEmpty());
	}
}

取交集
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al1 = new ArrayList();
		al1.add("java01");
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");

		ArrayList al2 = new ArrayList();
		al2.add("java01");
		al2.add("java03");
		al2.add("java06");
		
		//取交集,al1中只会保留与al2中相同的元素
		al1.retainAll(al2);
		System.out.println("al1 : "+al1);
		System.out.println("al2 : "+al2);
	}
}

去除两集合相同元素
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al1 = new ArrayList();
		al1.add("java01");
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");

		ArrayList al2 = new ArrayList();
		al2.add("java01");
		al2.add("java03");
		al2.add("java06");
		
		//移除包含的al2中的所有元素
		al1.removeAll(al2);
		System.out.println("al1 : "+al1);
		System.out.println("al2 : "+al2);
	}
}

元素的取出(重点):
迭代器:Iterator接口。
疑问神马是迭代器呢?
:其实就是集合的取出元素的方式。
迭代器原理:把取出方式定义在了集合的内部,这样取出方式就可以直接访问集合内的元素,那么取出方式就被定义成了内部类。而每个容器的数据结构不同,所以取出的动作细节也不一样,但都有共性:判断和取出,那么可以将这些共性抽取,就形成了Iterator接口。
疑问如何获取集合中的对象呢?
:通过一个对外提供的方法iterator();
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//获取迭代器对象
		Iterator it = al.iterator();
		//判断是否有元素
		while(it.hasNext()){
			//因为返回的是Object类型,所以要强制转换成String类
			String s = (String)it.next();
			System.out.println(s);
		}
	}
}

国外的写法
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//放到for循环中,局部变量用完后就会被垃圾回收,节省了空间。
		for(Iterator it = al.iterator();it.hasNext();){
			String s = (String)it.next();
			System.out.println(s);
		}
	}
}
Collection
|——List:元素是有序的,元素可以重复,因为该集合体系有索引。
|——Set:元素是无序的,元素不可以重复。
List特有方法:凡是可以操作角标的方法都是该体系特有的方法。
void add(int index, E element);在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection<? extends E> c);将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。 
E remove(int index);移除列表中指定位置的元素(可选操作)。 

E set(int index, E element);用指定元素替换列表中指定位置的元素(可选操作)。
E set(int index, E element);用指定元素替换列表中指定位置的元素(可选操作)。
List<E> subList(int fromIndex, int toIndex);返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
ListIterator<E> listIterator(int index);返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
采用for循环:
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		for(int x=0;x<al.size();x++){
			String s = (String)al.get(x);
			System.out.println(s);
		}
	}
}
采用Iterator
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		for(Iterator it = al.iterator();it.hasNext();){
			String s = (String)it.next();
			System.out.println(s);
		}
	}
}
列表迭代器ListIterator
练习:在迭代过程中,添加或者删除元素。
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//放到for循环中,局部变量用完后就会被垃圾回收,节省了空间。
		for(Iterator it = al.iterator();it.hasNext();){
			Object obj = it.next();
			if(obj.equals("java02")){
				al.add("java08");//添加
				//al.remove("java01");//删除
			}
			System.out.println(obj);
		}
	}
}

分析:发生了ConcurrentModificationException并发修改异常,产生原因在Iterator操作元素时,ArrayList也操作元素。
解决办法:要么使用迭代器的方法,要么使用集合的方法。
发现Iterator里没有添加操作,所以使用其子类ListIteratorList集合特有的迭代器ListIteratorIterator的子接口。在迭代时,不可以通过集合对象的方法操作集合的元素,因为会发生并发修改异常,所以在迭代时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,不能对元素进行判断,取出,删除的操作。如果想要其他的操作如:添加,修改等,就需要使用其子接口ListIterator。该接口只能通过List集合的listIterator();方法获取。
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//放到for循环中,局部变量用完后就会被垃圾回收,节省了空间。
		for(ListIterator it = al.listIterator();it.hasNext();){
			Object obj = it.next();
			if(obj.equals("java02")){
				it.add("java08");//添加
				//it.remove();//删除
			}
		}
		System.out.println(al);
	}
}

ArrayList:底层的数据结构使用的是数组结构。查询速度很快,但是增删速度稍慢。线程不同步,默认是10个长度,50%延长。
LinkedList:底层的数据结构使用是链表数据结构。增删速度很快,但是查询速度稍慢。(面试)
Vector:底层的数据结构使用是数组结构。1.0版本之后出现。线程同步。被ArrayList替代。100%延长。
数组结构

链表结构

最常用到的集合:
List:ArrayList,LinkerList
Set:HashSet
Map:HashMap
练习:Vector
import java.util.*;
class Demo
{
	public static void main(String args[]){
		Vector v = new Vector();
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
		Enumeration e = v.elements();
		while(e.hasMoreElements()){
			Object obj = e.nextElement();
			System.out.println(obj);
		}
	}
}
发现:枚举和迭代器很像。其实枚举和迭代器是一样的,因为枚举的名称及方法的名称都过长,所以别迭代器取代了。枚举郁郁而终。
LinkedList特有方法:
void addFirst(E e);将指定元素插入此列表的开头。
void addLast(E e);将指定元素添加到此列表的结尾。
E removeFirst();移除并返回此列表的第一个元素。
E removeLast();移除并返回此列表的最后一个元素。
E getFirst();返回此列表的第一个元素。
E getLast();返回此列表的最后一个元素。
import java.util.*;
class Demo
{
	public static void main(String args[]){
		LinkedList v = new LinkedList();
		v.removeFirst();
	}
}

分析:当集合为空时,调用removeFirst();NoSuchElementException没有这个的元素异常。
解决办法:1.6版本后,出现了pollFirst();获取并移除此列表的第一个元素,如果此列表为空,在返回null
import java.util.*;
class Demo
{
	public static void main(String args[]){
		LinkedList v = new LinkedList();
		v.pollFirst();
	}
}
1.6版本后出现的替代方法
boolean offerFirst(E e);在此列表的开头插入指定的元素。
boolean offerLast(E e);在此列表末尾插入指定的元素。
E peekFirst();获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekLast();获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
获取元素,但不删除元素。如果集合没有元素,会返回null
E pollFirst();获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast();获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
获取元素,但元素被删除。如果集合没有元素,会返回null
练习LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出。
import java.util.*;
class DuiZhan
{
	private LinkedList ll;
	DuiZhan(){
		ll = new LinkedList();
	}
	public void myAdd(Object obj){
		ll.offerFirst(obj);
	}
	public Object myGet(){
		return ll.pollFirst();
	}
	public boolean isNull(){
		return ll.isEmpty();
	}
}
class Demo
{
	public static void main(String args[]){
		DuiZhan dz = new DuiZhan();
		dz.myAdd("java01");
		dz.myAdd("java02");
		dz.myAdd("java03");
		dz.myAdd("java04");
		while(!dz.isNull()){
			System.out.println(dz.myGet());
		}
	}
}

队列:先进先出。
import java.util.*;
class DuiLie
{
	private LinkedList ll;
	DuiLie(){
		ll = new LinkedList();
	}
	public void myAdd(Object obj){
		ll.offerFirst(obj);
	}
	public Object myGet(){
		return ll.pollLast();
	}
	public boolean isNull(){
		return ll.isEmpty();
	}
}
class Demo
{
	public static void main(String args[]){
		DuiLie dl = new DuiLie();
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");
		while(!dl.isNull()){
			System.out.println(dl.myGet());
		}
	}
}

练习:去除ArrayList集合中的重复元素。
import java.util.*;
class Demo
{
	public static void main(String args[]){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java03");
		al.add("java04");
		al.add("java04");
		System.out.println(singleElement(al));
	}
	public static ArrayList singleElement(ArrayList al){
		ArrayList newAl = new ArrayList();
		Iterator it = al.iterator();
		while(it.hasNext()){
			Object obj = it.next();
			if(!newAl.contains(obj))
				newAl.add(obj);
		}
		return newAl;
	}
}

ArrayListLinkedList的选择:查询多用ArrayList,修改多用LinkedList
Set
|——HashSet:底层数据结构是哈希表。
疑问HashSet是如何保证元素唯一性的呢?
:是通过元素的两个方法:hashCode();equals();来完成的,如果元素的hashCode相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals
注:对于判断元素是否存在,以及删除元素等操作依赖的方法是元素的hashCodeequals方法。ArrayList只依赖equalsHashSet先判断hashCode再判断equals
练习:往HashSet集合中存入自定义对象,姓名和年龄相同为同一个人。
import java.util.*;
class Person
{
	private String name;
	private int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public void show(){
		System.out.println("name = "+name+",age = "+age);
	}
	public int hashCode(){
		System.out.println("hashCode run "+name);
		return 60;
	}
	public boolean equals(Object obj){
		Person p = (Person)obj;
		System.out.println("equals run "+name+"::"+p.name);
		return name.equals(p.name)&&age==p.age;
	}
}
class Demo
{
	public static void main(String args[]){
		HashSet hs = new HashSet();
		System.out.println(hs.add(new Person("zhangsan",20)));
		System.out.println(hs.add(new Person("wangwu",18)));
		System.out.println(hs.add(new Person("wangwu",18)));
	}
}

分析:可以看到,当hashcode相同时,集合开始调用对象的equals方法进行比较。可见HashSet会先判断hashCode值,如果相同则再对equals进行判断。
改进:为了减少判断次数,提高效率,可以对hashcode方法进行复写。
import java.util.*;
class Person
{
	private String name;
	private int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public void show(){
		System.out.println("name = "+name+",age = "+age);
	}
	public int hashCode(){
		System.out.println("hashCode run "+name);
		return name.hashCode()+age*31;
	}
	public boolean equals(Object obj){
		Person p = (Person)obj;
		System.out.println("equals run "+name+"::"+p.name);
		return name.equals(p.name)&&age==p.age;
	}
}
class Demo
{
	public static void main(String args[]){
		HashSet hs = new HashSet();
		System.out.println(hs.add(new Person("zhangsan",20)));
		System.out.println(hs.add(new Person("wangwu",18)));
		System.out.println(hs.add(new Person("wangwu",18)));
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值