7--包&集合(ArrayList、HashSet、HashMap)

1、包

1.1、包介绍

在操作系统中:不同的文件会放在不同的文件夹中。也就是使用文件夹来管理文件。

Java中给出包的概念:在硬盘上的体现就是文件夹。作用是用来管理不同的class文件。

java中定义包:

         使用package关键字。

注意:如果要给某个类定义它所在的包(文件夹),这时package定义包的语句必须放在所有代码的最前面。

使用eclipse可以快速的创建包:

包的命名规则:

       一般公司中,都会使用公司的域名倒着写,作为当前项目中的包名。

      域名:www.baidu.com  ;包名:com.baidu.项目名.子模块名.

以后在写类的时候,一定要记得定义包。

1.2、包之间的访问和使用

package com.kuaixueit.pack1;

public class Demo {
	public void run() {
		System.out.println("演示包之间的访问");
	}
}
package com.kuaixueit.pack2;

public class Fu {
	public void run() {
		System.out.println("Fu run 测试");
	}
}
package com.kuaixueit.pack2;

import com.kuaixueit.pack1.Demo;	// 导入其他包下的类

public class Test {
	public static void main(String[] args) {
		
		// 使用在com.baidu.demo包下的Demo类
		// com.kuaixueit.pack1.Demo d = new com.kuaixueit.pack1.Demo();
		Demo d = new Demo();
		d.run();
		// 访问同一个包下
		Fu f = new Fu();
		f.run();
	}
}

使用eclipse快速导入包:ctrl + shift + O

1.3、jar包

windows下的压缩文件:zip、RAR ,其实就是将某个文件打包成一个压缩文件。

jar包:它是java中的压缩文件。将多个文件使用Java的方式压缩之后生成的文件就称为jar包。

一般需要将文件压缩成jar包,这时不要使用windows的压缩工具,使用eclipse的导出功能。

1.4、权限访问修饰符

在定义类、成员变量、函数的时候,格式中都有修饰符。这个修饰符中有四个作为权限修饰。

public          公共的,它的权限最大。

protected    受保护的,如果某个成员变量、函数被protected修饰,这个成员变量或函数只能子类使用,其他类无法直接使用。

default(不写) 默认权限,不同包之间的类之间无法访问。

private       私有权限。只能在本类中访问。

2、集合(重点

2.1、介绍集合

变量:存放单个类型的常量数据。  int a = 123; a就是一个变量。  Person p = new Person(); p它是一个引用变量。

数组:它是存放具备一定数量的相同类型的数据。数组存储的数据量虽然变多,但是还是有局限。

集合:它是一个超大的容器。可以存放任意的对象,当存放的数据超过集合的容量,集合会自动扩容

以后在开发中,创建的对象基本都会使用集合进行存储。

在Java中将集合(类)容器分成了不同的场景使用:在学习集合时,需要掌握的是不同的集合它们的应用场景即可。

常用的集合容器:

         ArrayList

         HashSet

         HashMap

                   LinkedList:

                   TreeSet:

                   TreeMap:

Java中提供的集合相关的类都保存在java.util包下。

Java中的任何集合中保存的都是Java中的对象(元素),基本类型数据不能给集合中直接保存。

2.2、ArrayList集合介绍

2.2.1、介绍ArrayList

ArrayList集合(类)是开发中使用频率非常高的集合容器。查看它的API,会发现这个集合的继承体系和定义比较复杂,这些大家不用担心,随着我们技术的学习深入,都会慢慢的了解和掌握的。

ArrayList集合它可以像数组一样来存储new的对象,但是比数组强大很多。

2.2.2、演示ArrayList集合


/*
 * 演示 ArrayList集合的基本使用
 * 	集合属于容器:容器最基本的操作行为:
 * 	1、添加元素
 * 	2、删除元素
 * 	3、修改元素
 * 	4、获取元素
 * 	5、判断元素
 * 	6、遍历元素
 * 	集合必须掌握他们的增(C create )删(D delete)改(U update)查(R read),判断和遍历。
 */
public class ArrayListDemo {
	public static void main(String[] args) {
		
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");
		list.add("华安");
		list.add("对穿肠");
		list.add("华夫人");
		
		// 根据指定的下标添加
		list.add(1, "华文");
		// 打印
		System.out.println(list);
	}
}


	// 演示 删除 方法
	public static void demo2() {
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");	
		
		/*
		 *  演示删除方法
		 *  remove(Object obj) :
		 *  	将指定的对象从集合中删除,删除成功返回true,失败false
		 *  	如果集合中有多个, 删除的是第一个。
		 */
		boolean b = list.remove("石榴姐");
		/*
		 * remove(int index) :
		 * 		根据指定的下标,将当前位置上的元素删除。并返回被删除的那个元素
		 * 		要求指定的下标的位置上必须有数据。否则发生异常。
		 */
		Object obj = list.remove(4);
		System.out.println(b);
		System.out.println(list);
		System.out.println(obj);
	}

	/*
	 * 演示集合的修改方法
	 */
	public static void demo3() {
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");	
		System.out.println(list);
		/*
		 * set(int index , Object element ) :
		 * 	将指定位置上的值改掉。原来的值就没有了。
		 * 	要求指定的下标所在的位置空间中必须有数据。
		 */
		list.set(2, "凤姐");
		list.set(4, "刘能");
		System.out.println(list);
	}


	/*
	 * 使用普通的for可以遍历ArrayList集合
	 */
	public static void demo5() {
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");	
		
		for( int i = 0 ; i < list.size() ; i++ ){
			System.out.println(list.get(i));
		}
	}
	/*
	 * 查询
	 */
	public static void demo4() {
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");	
		
		/*
		 * get(int index) : 获取指定下标位置上的数据。要求下标位置上必须有数据
		 */
		Object obj = list.get(2);
		System.out.println(list);
		System.out.println(obj);
		
		/*
		 * size : 获取到的是集合中元素的数量(不一定是集合的容量)。
		 */
		int size = list.size();
		System.out.println(size);
		
	}

	// 演示集合的判断方法
	public static void demo() {
		/*
		 * 创建集合容器对象
		 */
		ArrayList list = new ArrayList();
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");	
		/*
		 * contains :判断指定的元素在集合中是否存在,存在返回true,否则返回false
		 */
		boolean b = list.contains("华安");
		System.out.println(b);
		/*
		 * isEmpty : 判断集合是否为空。集合存在,但是其中没有元素,返回true。
		 * 如果根本就没有集合,那么就无法调用集合中的任何方法
		 */
		boolean c = list.isEmpty();
		System.out.println(c);
	}

2.3、迭代(遍历)器

2.3.1、介绍迭代器

迭代器:它的主要功能就是用来遍历集合中的元素。迭代器对应的是Iterator。

由于Java中集合容器太多,每个集合容器都有自己的存储数据的方式。如果让集合的使用者记住每个集合各自如何存取数据,就会十分的麻烦,于是Java又对每个集合容器的存取的方式进行共性的抽取,将最简单遍历(取出)方式抽取到了Iterator中。

集合的遍历的原则:

         1、判断集合中有没有元素。

         2、如果有元素就取出当前这个元素。

2.3.2、演示迭代器

/*
 * 演示集合公用的遍历方式
 */
public class IteratorDemo {
	public static void main(String[] args) {
		
		/*
		 * 创建集合容器对象
		 */
		ArrayList list = new ArrayList();
		// 给集合中添加元素
		list.add("秋香");
		list.add("石榴姐");
		list.add("石榴姐");
		list.add("华安");	
		
		//System.out.println(list);
		/*
		 * 遍历容器中的每个元素,目的是取出这个元素,然后对元素进行其他的操作的。
		 */
		// 先基于这个容器(集合)得到遍历的对象
		Iterator it = list.iterator();
		/*
		 * 循环取出集合中的每个元素
		 * it.hasNext() : 判断集合中有没有元素的
		 * it.next() : 从集合中取出当前这个元素,取出的同时光标会移动当前这个元素的后面
		 */
		while( it.hasNext() ){
			System.out.println( it.next() );
		}
		System.out.println("===================");
		/*
		 * 上面的遍历器已经将集合从前往后遍历的一遍,那么基于当前这个遍历器的隐士光标
		 * 就已经移动了集合的最后一个元素的后面了,无法再使用这个遍历器对集合进行遍历
		 */
		while( it.hasNext() ){
			System.out.println( it.next() );
		}
		System.out.println("===================");
		/*
		 * 上面的迭代器,已经无法再对集合进行遍历,但是从我们学习变量的定义:
		 * 	只要从定义的地方开始往下,变量可以一直被使用。
		 * 于是建议将while循环改为for循环。
		 */
		for( Iterator it2 = list.iterator(); it2.hasNext() ; ){
			System.out.println( it2.next() );
		}
		
	}
}

2.3.3、迭代器的细节

1、迭代器需要通过iterator方法获取,当获取到之后,遍历结束迭代器隐式光标就已经移动到集合的最后一个元素的后面,无法再去遍历集合。

2、建议在遍历集合的时候,每调用一次hasNext方法,就只使用一次next方法。

/*
 * 迭代器的细节
 */
public class IteratorDemo2 {
	public static void main(String[] args) {
		
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		list.add("xue");
		list.add("java");
		list.add("xi'an");
		list.add("changan");
		list.add("wanke");
		System.out.println(list);
		/*
		 * 建议以后遍历集合的时候,最好使用for循环
		 */
		for( Iterator it = list.iterator() ; it.hasNext() ;  ){
			Object obj = it.next();
			System.out.println(it.next());
		}
	}
}

3、在使用Iterator遍历集合的时候,不要试图使用集合自身的增删方法对集合中的元素进行操作。

/*
 * 迭代器的细节
 */
public class IteratorDemo3 {
	public static void main(String[] args) {
		
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		list.add("xue");
		list.add("java");
		list.add("xi'an");
		list.add("changan");
		list.add("wanke");
		System.out.println(list);
		/*
		 * 建议以后遍历集合的时候,最好使用for循环
		 */
		for( Iterator it = list.iterator() ; it.hasNext() ;  ){
			Object obj = it.next();
			// 判断是否有"java"这个字符串,有就删除
			if( "java".equals(obj) ) {
				list.remove(obj);
			}
		}
	}
}

2.4、ArrayList的细节

ArrayList集合它的操作类似于数组,但是它会随着其中元素的增减会自动的扩容。而且其中还能够存放重复的元素,并且可以根据元素的下标来操作集合中的每个元素。

在集合的指定位置添加元素:必须保证指定的下标所在的空间前面的空间中有元素。

根据指定的下标,获取对应位置上的元素:必须保证指定的位置上有元素。

根据指定的下标删除当前位置上的元素。必须保证指定的位置上有元素。

根据指定的下标和元素,将指定位置上原有的元素替换掉。

从前往后获取指定元素第一次出现的下标,如果没有返回-1.

从后往前获取指定元素第一次出现的下标,如果没有返回-1.

public class ArrayListDemo2 {

	public static void main(String[] args) {
		// 创建集合对象
		ArrayList list = new ArrayList();
		
		list.add("我在零位置上");  // Collection中的add方法
		// 添加元素 
		list.add(1, "你猜报错吗?");  // List接口中自己的add方法
		System.out.println(list);
		// 删除方法
		list.remove(0);
		System.out.println(list);
		list.add(1, "你猜报错吗?");
		System.out.println(list);
		
		// 获取
		Object obj = list.get(0);
		//System.out.println(obj);
		// 修改
		list.set(0, "我是修改之后的数据");
		System.out.println(list);

	}
}	

3、ArrayList练习★★★★★★

3.1、需求

对学生信息的CRUD操作。

分析:

         1、让管理者可以选择操作的类别

                            A、添加学生

                            B、查询学生

                            C、修改学生

                            D、删除学生

                            E、退出管理

          2、根据管理者的选择,继续下一步动作

                 选择A:让管理者开始输入学生的详细信息,最后需要将学生的完整信息存储到集合中。

                 选择B:全部查询,将所有学生信息全部显示出来

                 选择C:修改需要先输入修改的条件,根据条件查询到底有没有这个数据,如果有就显示出来这个数据,然后提示进行修改。

        如果没有指定条件的数据,应该告诉管理者,输入的修改条件有误,重新输入修改条件。

                选择D:删除也需要条件,根据条件查询有没有,有就删除,删除之后提示删除成功信息。删除的条件查询不到数据,提示条件有误!

                 选择E:退出程序。

3.2、主程序代码

/*
 * 集合练习:学生信息的CRUD操作
 */
public class ArrayListTest {
	
	/*
	 * 定义成员变量,用来提供共同的获取键盘录入的类的对象
	 */
	private static Scanner sc = new Scanner( System.in );
	/*
	 * 定义集合容器对象,作为存储学生对象的容器。
	 */
	private static ArrayList list = new ArrayList();
	
	public static void main(String[] args) {
		System.out.println("==========欢迎使用学生信息管理平台===========");
		core();
		System.out.println("==========谢谢使用学生信息管理平台===========");
	}
	/*
	 *  核心的入口程序。提供让管理者选择的提示信息,
	 *  以及获取管理者选择的结果
	 */
	public static void core() {
		System.out.println("请选择需要操作的类型:");
		while(true){
			System.out.println("A:添加学生");
			System.out.println("B:查询学生");
			System.out.println("C:修改学生");
			System.out.println("D:删除学生");
			System.out.println("E:退出管理");
			// 获取管理者输入的操作类型
			String op = sc.nextLine();
			// 判断当前输入的操作类型到底对应的是哪一个
			if( op.equalsIgnoreCase("A") ){
				// 选择的添加学生信息
				addStudent();
			}
			else if( op.equalsIgnoreCase("B") ){
				// 选择的是查询学生信息
				findStudent();
			}
			else if( op.equalsIgnoreCase("C") ){
				// 选择的是修改学生信息
				updateStudent();
			}
			else if( op.equalsIgnoreCase("D") ){
				// 选择的是删除学生信息
				removeStudent();
			}
			else if( op.equalsIgnoreCase("E") ){
				// 选择的是退出管理
				return ; // break;
			}else{
				System.out.println("输入的操作方式不支持,请重新输入");
			}
		}
	}
	// 删除学生
	public static void removeStudent() {
		// 根据学生的name删除学生数据
		System.out.println("请输入学生姓名:");
		String name = sc.nextLine();
		/*
		 * 遍历集合,从前往后取出集合中的学生信息,
		 * 判断当前取出的学生的姓名和需要被删除的姓名是否相同,
		 * 相同就是删除这个学生的数据,并且推出删除。
		 * 如果将集合中的数据全部遍历一遍,也没有找到指定姓名的学生信息
		 * 说明指定的姓名对应的学生不存在
		 */
		for( Iterator it = list.iterator() ; it.hasNext() ; ){
			// 从集合中取出之后,需要将类型强制转成Student类型
			Student s = (Student)(it.next());
			// 判断当前这个学生的姓名是否是录入的姓名
			if( name.equals( s.getName() ) ){
				// 从集合中删除这个学生数据
				it.remove(); // 一定要使用迭代器自带的remove,不能使用集合自身的remove
				System.out.println("删除成功!!!");
				return ; // 删除完成,让程序结束
			}
		}
		System.out.println("删除失败,输入的姓名不存在!!!");
	}
	// 修改学生
	public static void updateStudent() {
		System.out.println("请输入修改的学生姓名:");
		String name = sc.nextLine();
		
		// 遍历集合,从中取出每个学生
		for( Iterator it = list.iterator() ; it.hasNext() ; ){
			// 从集合中获取学生
			Student s = (Student) it.next();
			// 判断姓名是否相同
			if( name.equals( s.getName() )){
				// 判断成立,说明这个学生是需要被修改的
				System.out.println(s); // 显示当前这个需要被修改的学生的数据
				/*
				 * 1、根据提示的类型进行修改
				 * 2、不管什么情况,全部修改
				 */
				System.out.println("请选择要修改的内容:");
				System.out.println("是否修改性别:Y/N");
				String opSex = sc.nextLine();
				
				System.out.println("是否修改电话:Y/N");
				String opTel = sc.nextLine();
				
				System.out.println("是否修改住址:Y/N");
				String opAddr = sc.nextLine();
				// TODO 需要分别处理修改性别、电话、住址的信息。目前有Bug
				// 判断上面的三个操作类型
				if( opSex.equalsIgnoreCase("Y") ){
					// 修改性别
					System.out.println("请输入要修改的性别:");
					String sex = sc.nextLine();
					s.setSex(sex);
					
				}else if( opSex.equalsIgnoreCase("N") ){
					System.out.println("选择不修改性别!!");
				}else{
					System.out.println("选择修改性别的类型有误!!");
				}
				
				if( opTel.equalsIgnoreCase("Y") ){
					// 修改电话
					System.out.println("请输入要修改的电话:");
					String tel = sc.nextLine();
					s.setTel(tel);
				}
				
				if( opAddr.equalsIgnoreCase("Y") ){
					// 修改住址
					System.out.println("请输入要修改的住址:");
					String addr = sc.nextLine();
					s.setAddr(addr);
				}
				
				System.out.println("修改成功!!!");
				System.out.println( s );
				return ;
			}
		}
		System.out.println("修改失败,输入的姓名不存在!!!");
	}
	// 查询学生
	public static void findStudent() {
		// TODO 在完成基本任务之后,需要完成条件查询
		System.out.println("A:全部查询");
		System.out.println("B:条件查询");
		if( ! list.isEmpty() ){
			// 先按照全部方式查询
			for( Iterator it = list.iterator(); it.hasNext() ; ){
				System.out.println( it.next() );
			}
		}else{
			System.out.println("还没有学生数据,请先去添加!!!");
		}
	}
	// 添加学生
	public static void addStudent() {
		System.out.println("请输入学生的姓名:");
		String name = sc.nextLine();
		
		System.out.println("请输入学生的性别:");
		String sex = sc.nextLine();
		
		System.out.println("请输入学生的电话:");
		String tel = sc.nextLine();
		
		System.out.println("请输入学生的住址:");
		String addr = sc.nextLine();
		
		// 需要将学生的信息封装到Student类上。
		Student s = new Student();
		// 封装数据
		s.setName(name);
		s.setSex(sex);
		s.setTel(tel);
		s.setAddr(addr);
		
		// 需要将学生的数据存储在集合容器中
		list.add( s );
		System.out.println("学生信息添加成功!!!");
	}
}

3.3、学生类

/*
 * 学生类,主要用于为程序提供Student对象,封装学生数据
 */
public class Student {
	private String name;
	private String sex;
	private String tel;
	private String addr;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getAddr() {
		return addr;
	}
	public void setAddr(String addr) {
		this.addr = addr;
	}
	/*
	 * 复写Object类中的toString方法,目的是希望在打印Student的引用的时候。
	 * 不要再显示内存地址信息,而是显示和Student自身对象有关的一些成员变量数据。
	 */
	public String toString() {
		return "Student [name=" + name + ", sex=" + sex + ", tel=" + tel + ", addr=" + addr + "]";
	}
	
}

4、HashSet集合

4.1、HashSet介绍

此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

HashSet集合:它不保证存放在集合中的元素的存取顺序。它可以保证元素不重复。

4.2、演示HashSet

/*
 * 演示HashSet集合
 */
public class HashSetDemo {
	public static void main(String[] args) {
		
		// 创建集合对象
		HashSet set = new HashSet();
		
		// 添加元素
		set.add("aaaa");
		set.add("aaaa");
		set.add("abc");
		set.add("abc");
		set.add("xyz");
		set.add("xyz");
		
		// 遍历
		for( Iterator it = set.iterator() ; it.hasNext() ;  ){
			System.out.println(it.next());
		}
		
	}
}

/*
 * 演示HashSet的基本使用
 */
public class HashSetDemo {
	public static void main(String[] args) {
		demo3();
	}
	// 遍历
	public static void demo3() {
		
		// 创建集合容器对象
		HashSet set = new HashSet();
		// 添加方法
		set.add("宋吉吉");
		set.add("马蓉");
		set.add("马蓉");
		set.add("王宝强");
		set.add("王宝强");
		set.add("马蓉他妈");		
		
		// 使用迭代器遍历HashSet集合
		for( Iterator it = set.iterator() ; it.hasNext() ; ){
			System.out.println( it.next() );
		}
		
	}
	// 判断、删除
	public static void demo2() {
		// 创建集合容器对象
		HashSet set = new HashSet();
		// 添加方法
		set.add("宋吉吉");
		set.add("马蓉");
		set.add("马蓉");
		set.add("王宝强");
		set.add("王宝强");
		set.add("马蓉他妈");		
		/*
		 *  判断的方法  contains :是否包含指定的元素
		 */
		boolean b = set.contains("马蓉");
		System.out.println(b);
		/*
		 * isEmpty : 判断集合是否为空
		 */
		boolean c = set.isEmpty();
		System.out.println(c);
		
		System.out.println(set);
		/*
		 * 删除方法:remove : 删除指定的元素,删除成功返回true
		 */
		boolean d = set.remove("马蓉");
		System.out.println(d);
		System.out.println(set);
	}
	// 添加元素
	public static void demo() {
		
		// 创建集合容器对象
		HashSet set = new HashSet();
		// 添加方法
		set.add("宋吉吉");
		set.add("马蓉");
		set.add("马蓉");
		set.add("王宝强");
		set.add("王宝强");
		set.add("马蓉他妈");
		
		System.out.println(set);
	}
}

4.3、演示HashSet中存放自定义对象

/*
 * 给HashSet中存放自定义对象
 */
public class HashSetDemo2 {
	public static void main(String[] args) {
		
		// 创建集合对象
		HashSet set = new HashSet();
		
		set.add( new Person("华安",28) );
		set.add( new Person("秋香",18) );
		set.add( new Person("秋香",18) );
		set.add( new Person("石榴",38) );
		set.add( new Person("华安",28) );
		
		// 遍历
		for (Iterator it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
	}
}

给HashSet中存放自定义对象的时候,发现同姓名同年龄的同一个人重复存放。而我们知道的HashSe集合是不能存放重复元素的。

重复的原因:

         每个给HashSet中存放对象的时候,都在创建新的Person对象,虽然会根据这个Person对象计算哈希值,确定它的存储位置。但是由于每次都是new的新的Person,这时计算哈希值的时候,其实会根据每个对象自己的内存地址计算哈希值。每次都在new对象,及时同姓名,同年龄,我们认为是同一个人,但是他们的内存地址不相同,计算出来的哈希值肯定也不相同。这样导致就会存放到哈希表中去。

解决这个问题:

         其实给哈希表中存放对象的时候,计算哈希值时是在调用当前类中的hashCode方法。如果一个类中没有书写hashCode方法,那么这个hashCode方法就是从Object类中继承到的。而Object类中的hashCode方法就是根据内存地址计算哈希值。

	/*
	 * 复写Object类中的hashCode方法。这样就可以保证在给哈希表中存放Person对象的时候
	 * 就会调用子类复写之后的hashCode方法,而不会调用Object类中的hashCode方法。
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

在Person类中添加完hashCode和equals方法之后,再去运行测试HashSet的类,重复的Person对象就没有了。

最终的结论:

HashSet中保持的任何对象,其实都在调用对象的hashCode算位置,调用equals比较对象是否相同。

因此要求如果自定义的类,一定要在自己的类中复写Object类中的hashCodeequals方法,根据当前这个类的

成员数据计算位置和判断是否相同,因此要求在自己的类中复写Object类中的hashCodeequals方法。

5、HashMap集合

ArrayList和HashSet集合它们中的确可以存放对象,但是对象和对象之间并没有什么关系。因此这两个集合经常成为单列集合。

有些数据(对象)之间会有一定的对应关系,如果将这些数据存放在ArrayList或HashSet的集合中,虽然可以存放数据,但是存放之后,对象之间的对应关系不好维护。这些具有一定对应关系的一组(一对)数据,我们就需要使用java中提供的HashMap集合存放它们。

HashMap集合:它可以存放具有一定对应关系的数据(key = value)。将键(key)映射到值(value)的对象。一个HashMap集合中不能包含重复的键(key);每个键最多只能映射到一个值(value)。

5.1、添加和修改方法

public class HashMapDemo {
	public static void main(String[] args) {

		// 创建集合对象
		HashMap map = new HashMap();
		// 添加元素
		Object o = map.put("西安", "陕西");
		map.put("郑州", "河南");
		System.out.println(o);
		// 直接打印
		System.out.println(map);
		o = map.put("成都", "四川");
		System.out.println(o);
		System.out.println(map);
	}
}

put方法:它本身是将指定的key和value保存的hashmap集合中。如果当前指定的key在hashmap集合中已经存在,这时就会使用后面的value覆盖掉hashmap中key对应的原来的value值。并且返回被覆盖原来的value值。如果是第一次保存,key在hashmap中肯定不存在,那么返回的null。

5.2、删除方法

remove方法是将Map中的key和value同时移除。如果key在集合中不存在,返回null。

public class HashMapDemo2 {
	public static void main(String[] args) {

		// 创建集合对象
		HashMap map = new HashMap();
		map.put("西安","陕西");
		map.put("成都","四川");
		map.put("郑州","河南");
		System.out.println(map);
		
		Object obj = map.remove("济南");
		System.out.println(obj);
		System.out.println(map);
		map.clear();
		System.out.println(map);
	}
}

5.3、判断方法

public class HashMapDemo3 {
	public static void main(String[] args) {

		// 创建集合对象
		HashMap map = new HashMap();
		map.put("西安","陕西");
		map.put("成都","四川");
		map.put("郑州","河南");
		System.out.println(map);
		
		// 判断有没有“西安”字符串作为key
		boolean b = map.containsKey("西安");
		System.out.println(b);
		// 判断有没有“湖南”字符串作为value值
		boolean c = map.containsValue("湖南");
		System.out.println(c);
		// 判断集合是否为空集合
		boolean d = map.isEmpty();
		System.out.println(d);
	}
}

5.4、获取方法

记住:HashMap集合中的key不重复。针对HashMap集合的操作,一般都是通过key进行的。只能通过key操作value,不能通过value操作key

5.5、HashMap集合的遍历

HashMap集合不能直接使用Iterator进行遍历,必须将HashMap集合转成单列(ArrayList或HashSet)等其他单列集合,然后使用Iterator进行遍历。

5.5.1、keySet方法

keySet是将Map集合中的所有key取出来,然后保存到了一个Set集合中。

/*
 * 演示使用Map中的keySet方法对map集合进行遍历
 */
public class KeySetDemo {

	public static void main(String[] args) {
		
		// 创建集合对象
		HashMap map = new HashMap();
		
		map.put("赵四", "象牙山");
		map.put("谢大脚", "大脚超市");
		map.put("刘能", "地里");
		map.put("谢广坤", "苹果园");
		map.put("王大拿", "温泉山庄");
		
		// 遍历: 1、需要先获取到所有key组成的Set集合
		Set set = map.keySet();
		// 2、 使用Iterator遍历Set集合
		for( Iterator it = set.iterator(); it.hasNext() ; ){
			// 3、从Set中取出每个key
			Object key = it.next();
			// 4、通过key调用Map中的get方法,得到key对应的value值
			Object value = map.get(key);
			System.out.println(key+"...."+value);
		}
	}
}

5.5.2、entrySet方法

 entrySet方法:它主要是将Map中的key和value这一组(一对)数据重新封装成一个新的Entry对象。然后将所有Entry对象保存在Set集合中。最后我们去遍历Set集合,取出每个Entry对象,将相当于得到了Map中的每组key和value。

/*
 * 演示  使用entrySet方法遍历Map集合
 */
public class EntrySetDemo {
	public static void main(String[] args) {
		
		// 创建集合对象
		HashMap map = new HashMap();
		
		map.put("赵四", "象牙山");
		map.put("谢大脚", "大脚超市");
		map.put("刘能", "地里");
		map.put("谢广坤", "苹果园");
		map.put("王大拿", "温泉山庄");
	
		// 遍历
		// 1、调用entrySet,将每组key和value封装成Entry对象,保存到Set集合中
		Set set = map.entrySet();
		// 2、 遍历Set集合
		for( Iterator it = set.iterator() ;it.hasNext() ; ){
			// 3、 从Set中取出Entry对象。
			Object obj = it.next();
			/*
			 *  由于从Set中取出的对象被提升成Object类型, 
			 *  这时我们需要使用的Entry中的getKey和getValue方法。需要向下转型
			 */
			Entry entry = (Entry) obj;
			// 4、 调用getKey和getValue方法
			Object key = entry.getKey();
			Object value = entry.getValue();
			System.out.println(key + "=====" + value);
		}
	}
}

5.5.3、values方法

values方法:得到是Map中的所有的value值。

/*
 * 演示value方法
 */
public class ValuesDemo {
	public static void main(String[] args) {
		
		// 创建集合对象
		HashMap map = new HashMap();
		
		map.put("赵四", "象牙山");
		map.put("谢大脚", "大脚超市");
		map.put("刘能", "地里");
		map.put("谢广坤", "苹果园");
		map.put("王大拿", "温泉山庄");
		
		// 获取所有的value值
		Collection coll = map.values();
		for( Iterator it = coll.iterator() ;  it.hasNext() ; ){
			System.out.println(it.next());
		}
	}
}

6、思考:

既然集合是用来存储对象的。任何的对象都可以给集合中存放。创建的String对象、Person对象,以及其他的任何对象都可以给ArrayList、HashSet、HashMap集合中保持。

思考:集合也是对象,集合中能不能存储集合。如果可以,如何去遍历集合中的集合。遍历就需要借助多层循环嵌套。

猜你喜欢

转载自blog.csdn.net/baozi7263/article/details/105559439