欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 JAVA13——容器(Map接口、Equals和hashcode、Set接口、容器存储数据练习、Iterator接口)

程序员文章站 2022-05-04 19:10:01
目录Map接口主要方法实现Map第一种方式(不完美)第二种方式Equals和hashcodeSet接口实现Set容器存储数据练习Iterator接口迭代Map的两种遍历方式Map接口实现Map接口的类用来存储键(key)—值(value)对Map接口的实现类有HashMap和TreeMap等Map类中存储的键—值对通过键来标识,所以键值不能重复主要方法添加/改变一个键值对:Object put(Object key, Object value...

目录

Map接口

主要方法

实现Map

第一种方式(不完美)

第二种方式

Equals和hashcode

Set接口

实现Set

容器存储数据练习

Iterator接口

迭代Map的两种遍历方式


Map接口

  • 实现Map接口的类用来存储键(key)—值(value)对
  • Map接口的实现类有HashMap和TreeMap等
  • Map类中存储的键—值对通过键来标识,所以键值不能重复

主要方法

  • 添加/改变一个键值对:Object put(Object key, Object value)
  • 获取指定键对应的值:Object get(Object key)
  • 删除某个键值对:Object remove(Object key)
  • 删除指定索引的元素:int remove(int index)
  • 判断有没有指定key的对象:boolean containsKey(Object key)
  • 判断有没有指定value的对象:boolean containsValue(Object value)
  • 判断Map是否为空:boolean isEmpty()
  • 将一个Map的所有键值对加入到另一个Map中:void putAll(Map t)
  • 清空Map:void clear()
  • 获取Map大小:int size()

实现Map

第一种方式(不完美)

不完美的地方:每次查询和增加键值对都要遍历一次,效率低

public class MyMap01 {

	MyEntry[] arr = new MyEntry[990];
	int size;
	
	public void put(Object key, Object value){
		MyEntry e = new MyEntry(key, value);
		
		for(int i=0;i<size;i++){
			if(arr[i].key.equals(key)){
				arr[i].value = value;
				return;
			}
		}
		
		arr[size++] = e;
	}
	
	public Object get(Object key){
		for(int i=0;i<size;i++){
			if(arr[i].key.equals(key)){
				return arr[i].value;
			}
		}
		return null;
	}
	
	public boolean containsKey(Object key){
		for(int i=0;i<size;i++){
			if(arr[i].key.equals(key)){
				return true;
			}
		}
		return false;
	}
	
	public static void main(String[] args) {
		MyMap01 map = new MyMap01();
		map.put("张三", new Wife("李四"));
		map.put("张三", new Wife("李m"));
		
		Wife w = (Wife) map.get("张三");
		
		System.out.println(w.name);
		System.out.println(map.size);
	}
	
}

class MyEntry{
	Object key;
	Object value;
	
	public MyEntry(Object key, Object value){
		super();
		this.key = key;
		this.value = value;
	}
}

第二种方式

利用hashCode()方法

Map底层实现:数组+链表

import java.util.LinkedList;

public class MyMap02 {
	LinkedList[] arr = new LinkedList[999];
	int size;
	
	public void put(Object key, Object value){
		MyEntry e = new MyEntry(key, value);
		
		int hash = key.hashCode();
		hash = hash<0?-hash:hash;
		
		int a = key.hashCode()%arr.length;
		if(arr[a]==null){
			LinkedList list = new LinkedList();
			arr[a] = list;
			list.add(e);
		}else{
			LinkedList list = arr[a];
			for(int i=0;i<list.size();i++){
				MyEntry e2 = (MyEntry) list.get(i);
				if(e2.key.equals(key)){
					e2.value = value; //键值重复直接覆盖
				}
			}
			arr[a].add(e);
		}
	}
	
	public Object get(Object key){
		int a = key.hashCode()%arr.length;
		if(arr[a]!=null){
			LinkedList list = arr[a];
			for(int i=0;i<list.size();i++){
				MyEntry e = (MyEntry) list.get(i);
				if(e.key.equals(key)){
					return e.value;
				}
			}
		}
		return null;
	}
	
	
	public static void main(String[] args) {
		MyMap01 map = new MyMap01();
		map.put("张三", new Wife("李四"));
		map.put("张三", new Wife("李m"));
		
		Wife w = (Wife) map.get("张三");
		
		System.out.println(w.name);
	}
	
}

Equals和hashcode

  • Collection类对象在调用remove、 contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和hashCode方法;对于自定义的类型,需要重写equals和hashCode方法以实现自定义的对象相等规则
    • Java中规定,两个内容相同的对象应该具有相等的hash codes

重写Equals和hashcode eg:
source—Generate hashCode() and Equals()
重写id的Equals和hashcode方法:

public class Student {
	private int id;
	private String name;
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)	//判断地址是否一样
			return true;
		if (obj == null)	//判断传入的参数是否为空值
			return false;
		if (getClass() != obj.getClass())	//判断所在类是否一样
			return false;
		Student other = (Student) obj;	
		if (id != other.id)		//判断id值是否一样
			return false;
		return true;
	}
}

eg2:

public class TestEquals {
	
	public static void main(String[] args) {
		Map map = new HashMap();
		
		String s1 = new String("aaa");
		String s2 = new String("aaa");
		
		map.put(s1,"AAA");
		map.put(s2,"BBB");
		System.out.println(map.get("aaa"));
		
		Integer s3 = new Integer(123);
		Integer s4 = new Integer(123);
		
		map.put(s3,"AAA");
		map.put(s4,"BBB");
		
		System.out.println(map.get(123));
		
		Date s5 = new Date(123);
		Date s6 = new Date(123);
		
		map.put(s5,"AAA");
		map.put(s6,"BBB");
	
		System.out.println(map.get(s5));
	}
	
}

Set接口

  • Set接口是 Collection接口的子接口,Set接口没有提供额外的方法,Set接口的特性是容器类中的元素是没有顺序的,而且不可以重复
  • Set容器可以与数学中“集合”的概念相对应
  • J2SDK API中所提供的Set容器类有HashSet、TreeSet等

实现Set

import java.util.HashMap;

public class MyHashSet {
	
	HashMap map;
	int size;
	private static final Object PRESENT = new Object();
	
	public MyHashSet(){
		map = new HashMap();
	}
	
	public int size(){
		return map.size();
	}
	
	public void add(Object o){
		map.put(o, PRESENT);	//set的不可重复是利用了map里键对象的不可重复
	}
	
	public static void main(String[] args) {
		MyHashSet s = new MyHashSet();
		s.add("aaa");
		s.add(new String("aaa"));
		System.out.println(s.size());
	}
	
}

容器存储数据练习

存储如下表格中的数据:

ID 姓名 薪水 单位 入职时间
0301 AA 3000 项目部 2019-12
0302 BB 6000 教学部 2020-01
0303 CC 2000 教学部 2020-05

步骤:

一、创建Employee实体类

1.一个表对应一个类,创建类Employee,定义属性:

private int id;
private String name;
private int salary;
private String department;
private Date hireDate;

2.生成所有属性的Set和Get方法,生成构造器

修改构造器代码如下:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public Employee(int id, String name, int salary, String department,
		String hireDate) {
	super();
	this.id = id;
	this.name = name;
	this.salary = salary;
	this.department = department;
	
	DateFormat format = new SimpleDateFormat("yyyy-MM");
	try {
		this.hireDate = format.parse(hireDate);
	} catch (ParseException e) {
		e.printStackTrace();
	}
}

Employee类属于Javabean,即实体类

二、填入数据

第一种方法:

1.新建类Test01,创建对象并赋初值

一个对象对应了一行记录

public class Test01 {
	
	public static void main(String[] args) {
		Employee e = new Employee(0301, "AA", 3000, "项目部", "2019-12");
		Employee e2 = new Employee(0302, "BB", 6000, "教学部", "2020-01");
		Employee e3 = new Employee(0303, "CC", 2000, "教学部", "2020-05");
	}
	
}

创建ArrayList,将创建的对象存储到列表中

List<Employee> list = new ArrayList<Employee>();	//<Employee>代表该list只能存放Employee类
		
list.add(e);
list.add(e2);
list.add(e3);

3.创建获取所有对象name属性的函数,在main函数中调用

public static void printEmpName(List<Employee> list){	//只能传入存储Employee对象的列表
    for(int i=0;i<list.size();i++){
		System.out.println(list.get(i).getName());
	}
}
printEmpName(list);

第二种方法:

1.新建类Test02,创建对象并赋初值

一个map对应了一行记录

public class Test02 {
	
	public static void main(String[] args) {
		Map map = new HashMap();
		map.put("id", 0301);
		map.put("name", "AA");
		map.put("salary", 3000);
		map.put("department", "项目部");
		map.put("hireDate", "2019-12");
		
		Map map2 = new HashMap();
		map2.put("id", 0302);
		map2.put("name", "BB");
		map2.put("salary", 6000);
		map2.put("department", "教学部");
		map2.put("hireDate", "2020-01");
		
		Map map3 = new HashMap();
		map3.put("id", 0303);
		map3.put("name", "CC");
		map3.put("salary", 2000);
		map3.put("department", "教学部");
		map3.put("hireDate", "2020-05");
	}
	
}

2.创建ArrayList,将创建的map存储到列表中

List<Map> list = new ArrayList<Map>();	
		
list.add(map);
list.add(map2);
list.add(map3);

3.创建获取所有对象name属性的函数,在main函数中调用

public static void printEmpName(List<Map> list){	
	for(int i=0;i<list.size();i++){
		Map tempMap = list.get(i);
		System.out.println(tempMap.get("name"));
	}
}
printEmpName(list);

Iterator接口

  • 所有实现了Collection接口的容器类都有—个 iterator方法用以返回一个实现了Iterator接口的对象
  • Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作
  • Iterator接口定义了如下方法:
    • 判断是否有元素没有被遍历:boolean hasNext()
    • 返回游标当前位置的元素并将游标移动到下一个位置:Object next()
    • 删除游标左面的元素,在执行完next之后该操作只能执行一次:void remove()

eg:

public class Test01 {
	
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");
		
		//通过索引遍历list
		for(int i=0;i<list.size();i++){
			System.out.println(list.get(i));
		}
		
		//通过迭代器遍历list
		for(Iterator iter=list.iterator();iter.hasNext();){
			String str = (String) iter.next();
			System.out.println(str);
		}
		
		Set set = new HashSet();
		set.add("高1");
		set.add("高2");
		set.add("高3");
		
		//while循环
		Iterator iter2 = set.iterator();
		while(iter2.hasNext()){
			String str = (String) iter2.next();
			System.out.println(str);
		}
		
		//for循环
		for(Iterator iter3=set.iterator();iter3.hasNext();){
			String str = (String) iter3.next();
			System.out.println(str);
		}
	}
	
}

迭代Map的两种遍历方式

public class Test02 {
	
	public static void main(String[] args) {
		Map map = new HashMap();
		map.put("AA", "www");
		map.put("BB", "ddd");
		map.put("CC", "yyy");
		
		//迭代key,通过key获取value
		Set keys = map.keySet();
		for(Iterator iter = keys.iterator();iter.hasNext();){
			String keyStr = (String) iter.next();
			System.out.println(keyStr+"——"+map.get(keyStr));
		}
		
		//获取到所有的键值存到Set集合中,再迭代这个集合
		Set<Map.Entry<String,String>> entry = map.entrySet();
		Iterator<Map.Entry<String,String>>  ite = entry.iterator();
		while(ite.hasNext())
		{
			Map.Entry<String,String> en = ite.next();
			String key = en.getKey();
			String value = en.getValue();
			System.out.println(key+"=="+value);
		}
	}
	
}

 

本文地址:https://blog.csdn.net/qiao39gs/article/details/107361908

相关标签: JAVA基础 java