Map集合的子实现类HashMap,LinkedHashMap,TreeMap,和Exception

HashMap:

HashMap集合也基于哈希表:

  保证了键的唯一性,Map只针对键有效

并且元素的是无序的,存储与取出不一致

哈希表底层也依赖于:hashcode()与equals()方法

对于自定义类:该类要重写hashcode()和equals()方法

package org.westos;

public class Student {
String name;
int age;
public Student() {
	super();
	// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
	super();
	this.name = name;
	this.age = age;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}

@Override
public String toString() {
	return "Student [name=" + name + ", age=" + age + "]";
}
@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;
	Student other = (Student) 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;
}

}

package org.westos.HashMap;

import java.util.HashMap;
import java.util.Set;

import org.westos.Student;

public class HAshMapDemo1 {
public static void main(String[] args) {
	HashMap<Student,String> hm=new HashMap<Student,String>();
	Student s1=new Student("王菲",45);
	Student s2=new Student("杨千嬅",23);
	Student s3=new Student("莫文蔚",44);
	Student s4=new Student("谢春花",25);
	Student s5=new Student("Adile",29);
	Student s6=new Student("王菲",45);
	Student s7=new Student("杨千嬅",23);
	Student s8=new Student("莫文蔚",44);
	Student s9=new Student("谢春花",25);
	hm.put(s1, "北京");
	hm.put(s2, "香港");
	hm.put(s3, "香港");
	hm.put(s4, "浙江");
	hm.put(s5, "伦敦");
	hm.put(s6, "北京");
	hm.put(s7, "香港");
	hm.put(s8, "香港");
	hm.put(s9, "浙江");
 System.out.println(hm);
Set<Student> set=hm.keySet();
for(Student s:set)
	System.out.println(s+"---"+hm.get(s));
}
}
LinkedHashMap<K,V> :是Map接口基于哈希表和链接列表实现的
 
 哈希表保证键的唯一性

 链接列表保证元素有序性(存储和取出一致)

package LinkedHashMapDemo;

import java.util.ArrayList;
import java.util.LinkedHashMap;

public class LinkedHashMapDemo {
	public static void main(String[] args) {
		// 创建一个LinkedHashMap集合,该集合的键为ArrayList集合
		LinkedHashMap<ArrayList<String>, String> lhm = new LinkedHashMap<ArrayList<String>, String>();
		ArrayList<String> al = new ArrayList<String>();
		al.add("111");
		al.add("222");
		ArrayList<String> al2 = new ArrayList<String>();
		al2.add("111");
		al2.add("222");
		al2.add("333");
		ArrayList<String> al3 = new ArrayList<String>();
		al3.add("111");
		al3.add("222");
		al3.add("333");
		ArrayList<String> al5 = new ArrayList<String>();
		al5.add("111");
		al5.add("222");
		ArrayList<String> al6 = new ArrayList<String>();
		al6.add("111");
		al6.add("222");
		al6.add("111");
		al6.add("222");

		lhm.put(al, "学");
		lhm.put(al2, "习");
		lhm.put(al3, "使我");
		lhm.put(al6, "快乐");
		lhm.put(al5, "呀");
		// 遍历该集合
		System.out.println(lhm);
		for (ArrayList<String> al1 : lhm.keySet()) {
			for (String str : al1)
				System.out.print(str + "--");
			System.out.println(lhm.get(al1));
		}
	}
}

TreeMap集合:

保证了键的的唯一性

元素根据键的高低进行排列

package TreeMap;

public class Student {
private String name;
int age;
public Student() {
	super();
	// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
	super();
	this.name = name;
	this.age = age;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}
@Override
public String toString() {
	return "Student [name=" + name + ", age=" + age + "]";
}



}
package TreeMap;

import java.util.Comparator;
import java.util.TreeMap;

public class TreeMapDemo {
	public static void main(String[] args) {
		//创建TreeMap集合,并创建Comparator的匿名对象,重写Compare()方法
		TreeMap<Student, String> tm = new TreeMap<Student, String>(new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
				// TODO Auto-generated method stub
				int a = s1.age - s2.age;
				a = a == 0 ? s1.getName().compareTo(s2.getName()) : a;
				return a;
			}
		});
		//添加元素
		Student s1 = new Student("杨过", 23);
		Student s2 = new Student("郭靖", 23);
		Student s3 = new Student("令狐冲", 25);
		Student s4 = new Student("张无忌", 25);
		Student s5 = new Student("韦小宝", 20);
		Student s6 = new Student("韦小宝", 20);
		tm.put(s1, "宋朝");
		tm.put(s2, "宋朝");
		tm.put(s3, "不知道朝");
		tm.put(s4, "元朝");
		tm.put(s5, "错朝");
		tm.put(s6, "清朝");
 
	  System.out.println(tm);	
	  //遍历元素
	  for(Student s:tm.keySet())
		  System.out.println(s+"---"+tm.get(s));
	}
}

面试题:

      HashMap集合与Hashtable的区别?

        共同点:都是Map接口的实现类,都是基于哈希表的实现类

         HashMap:线程不安全的类,不同步,执行效率高(允许键和值为null)

          Hashtable:线程安全的类,同步的,执行效率低(不允许键和值为null)

线程安全的类:

      StringBuffer:字符串缓冲区

      Vector:List集合的

      Hashtable:Map集合的

 
package Map;

import java.util.HashMap;
import java.util.Hashtable;

public class HashtableDemo {
public static void main(String[] args) {
	Hashtable<String,Integer> ht=new Hashtable<String,Integer>();
	//ht.put(null, null);//运行报错java.lang.NullPointerException,存储的键值码不能为null
	//ht.put(null,2);
	ht.put("qwer", 2);
	//ht.put("a", null);
	ht.put("asdf", 1);
	ht.put("asdf", 1);
	ht.put("zxcv", 3);
	ht.put("bnm", 4);
	ht.put("tyuiop", 1);
	System.out.println(ht);
	System.out.println("----------");
	HashMap<String,Integer> hm=new HashMap<String,Integer>();
   	//hm.put(null, null);
	hm.put("qwer",3 );
	hm.put("asdf", null);
	hm.put("bnm",1);
	hm.put(null,2);
	System.out.println(hm);
	
}
}
需求:
  字符串:比如: aaaaabbbbcccddddee   ,最终控制台要出现的结果:a(5)b(4)c(3)d(3)e(2)
package Map;

import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo {
	public static void main(String[] args) {
		// 给出一个字符串
		String str = "aaaaaabbbbbbbbbbccccccdddddddddeeee";
		// 创建一个TreeMap集合
		TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
		// 将该字符串转换为字符数组
		char[] ch = str.toCharArray();
		// 遍历该数组
		for (char ch1 : ch) {
			// 当集合中没有存储该字符对应的键,获取该键对应的值为null
			Integer i = tm.get(ch1);
			if (i == null)
				tm.put(ch1, 1);
			else if (i != null)
				tm.put(ch1, ++i);
		}
		System.out.println(tm);
		Set<Character> set = tm.keySet();
		StringBuffer sb = new StringBuffer();
		System.out.println(sb);
		for (Character ch2 : set)
			sb.append(ch2 + "(" + tm.get(ch2) + ")");
		String str1 = sb.toString();
		System.out.println(str1);
	}
}

Collection与Collections的区别:

        Collection:是定层次单列集合的根接口,是一个集合,也是个接口

        Collections:是针对集合操作的工具类

           她的一些功能:

  public static <T>int binarySearch(List<T> list,key):使用二分法查找该集合中的元素

  public static T max(Collection c):获去该集合中的最大值

  public static void reverse(List<T> list):将该集合中的元素反转

  public static void Shuffle(List<T> List):将该集合元素的顺序打乱

  public static void sort(List<T> list)将该集合的元素进行排序

package Collections;

public class Student {
String name;
int age;
public Student() {
	super();
	// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
	super();
	this.name = name;
	this.age = age;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}
@Override
public String toString() {
	return "Student [name=" + name + ", age=" + age + "]";
}

}

package Collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;

public class CollectionsDemo {
	public static void main(String[] args) {
		// 创建ArrayList集合,并添加元素
		ArrayList<Student> al = new ArrayList<Student>();
		Student s1 = new Student("林俊杰", 35);
		Student s2 = new Student("周杰伦", 35);
		Student s3 = new Student("王杰", 45);
		Student s4 = new Student("陈百强", 62);
		Student s5 = new Student("谭咏麟", 62);
		al.add(s1);
		al.add(s2);
		al.add(s3);
		al.add(s4);
		al.add(s5);
		System.out.println(al);
		for (Student s : al)
			System.out.println(s);
		System.out.println("-------------");
		// 将该集合排序
		Collections.sort(al, new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
				// TODO Auto-generated method stub
				int a = s1.age - s2.age;
				a = (a == 0) ? (s1.name.compareTo(s2.name)) : a;
				return a;
			}
		});
		for (Student s : al)
			System.out.println(s);
		System.out.println("-----------");
		// 将该集合元素的顺序打乱
		Collections.shuffle(al);
		System.out.println(al);
		for (Student s : al)
			System.out.println(s);
		System.out.println("-----------");
		// 将该集合反转
		Collections.reverse(al);
		System.out.println(al);
		for (Student s : al)
			System.out.println(s);
		System.out.println("-----------");
		// 获取该集合的元素最大值
		Student s = Collections.max(al, new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
				// TODO Auto-generated method stub
				int a = s1.age - s2.age;
				a = (a == 0) ? (s1.name.compareTo(s2.name)) : a;
				return a;
			}

		});
		System.out.println(s);
	}
}
模拟斗地主的洗牌和发牌,发到每一个手上的牌是保证有序的.. 思考: 1)创建牌盒
 创建两个集合:HashMap<Integer,String>,ArrayList<Integer> 2)装牌 定义花色数组和点数数组
  从0开始编号,将编号和编号对应的牌都存储到HashMap集合中,同时往ArrayList单独存储编号 3)洗牌 洗的是编号 4)发牌

  发的也是编号,为了保证牌有序,集合由TreeSet集合接收 5)看牌 封装功能

package Porker;

import java.util.ArrayList;

import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class porkerDemo {
	public static void main(String[] args) {
		// 定义花色与点数
		String[] str = { "♥", "♠", "♣", "◆" };
		String[] str2 = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2" };
		// 创建牌盒HashMap获取牌与牌对应的编号,ArrayList获取牌对应的编号
		HashMap<Integer, String> hm = new HashMap<Integer, String>();
		ArrayList<Integer> al = new ArrayList<Integer>();
		// 拼接花色与点数
		int index = 0;
		for (String str3 : str)
			for (String str4 : str2) {
				String str5 = str3.concat(str4);
				hm.put(index, str5);
				al.add(index);
				index++;
			}
		// 获取小王
		hm.put(index, "小王");
		al.add(index);
		index++;
		// 获取大王
		hm.put(index, "大王");
		al.add(index);
		System.out.println(hm);
		// 洗牌
		Collections.shuffle(al);
		// 创建TreeSet集合分别获取三个玩家的牌和底牌对应的编号并排序
		TreeSet<Integer> player1 = new TreeSet<Integer>();
		TreeSet<Integer> player2 = new TreeSet<Integer>();
		TreeSet<Integer> player3 = new TreeSet<Integer>();
		TreeSet<Integer> dipai = new TreeSet<Integer>();
		for (int i = 0; i < al.size(); i++) {
			if (i >= al.size() - 3)
				dipai.add(al.get(i));
			else if (i % 3 == 1)
				player1.add(al.get(i));
			else if (i % 3 == 2)
				player2.add(al.get(i));
			else if (i % 3 == 0)
				player3.add(al.get(i));
		}
		// 看牌
		lookPoker("玩家1", player1, hm);
		lookPoker("玩家2", player2, hm);
		lookPoker("玩家3", player3, hm);
		lookPoker("底牌", dipai, hm);
	}
	// 实现看牌的功能
	public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) {
		System.out.println(name + "的牌是:");
		for (Integer i : ts)
			System.out.print(hm.get(i));
		System.out.println();
	}
}

Exception:

 当程序出现一些问题的,可以是严重问题,可以是一种异常,将这些通常为Throwable
 Throwable 类是 Java 语言中所有错误或异常的超类
  Throwable
  error
exception
  举例:
   张三去山上旅行
   1)张三骑车去旅行,山路崩塌了,不能前行了----->不可抗力因素
   2)张三骑车去旅行,骑着发现轮胎没气了------->需要检查的问题
   3)骑着,山路有石子,他就非得往石子上骑,导致车胎没气了---->自己原因造成的,no zuo no die
  
  不抗力因素----->error: 属于严重问题   内存溢出了 (加载页面中大量图片的时候,程序会挂掉---使用第三方的框架去处理:ImageLoader)
 异常:
  编译时期异常:只要出现的不是运行时期异常,统称为编译时期  日期的文本格式---解析   java.util.Date类型:ParseException:解析异常
   编译时期异常:开发者必须处理!
   运行时期异常:RuntimeException
   编译通过了,但是开发者代码不严谨(NullPointerExceptino等等...)

 try{
  一些代码
  try里面的代码越少越好
  代码包含了可能会出现问题的代码
 }catch(异常类 异常类对象){
  try出现异常了,描述的异常刚好就是catch的异常类,就会执行catch里面代码
  处理异常
 }
package Exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo1 {
public static void main(String[] args) {
	int a=1;
	int b=0;
	String str="1996--10--19";
	try {
	System.out.println(a/b);
	}catch(ArithmeticException e) {
		System.out.println("除数不能为0");
	}
	try {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy--MM--dd--hh");
		Date d=sdf.parse(str);
	}catch(ParseException e) {
		System.out.println("解析异常");
		e.printStackTrace();
	}
}
}

如何处理多个异常
  两个或两个以上的异常的时候怎么办?
 
   try{
   可能出现问题的代码
   }catch(异常类名1 对象名1){
   异常处理
   }catch(异常类名2 对象名2(){
               异常处理
  }

package Exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo2 {
	public static void main(String[] args) {
		int a = 1;
		int b = 0;
		String str = "1996--10--19";
		try {
			// 只会处理一个异常
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy--MM--dd--hh");
			Date d = sdf.parse(str);
			System.out.println(a / b);
		} catch (ArithmeticException e) {
			System.out.println("除数不能为0");
		} catch (ParseException e) {
			System.out.println("解析异常");
			e.printStackTrace();
		}
	}
}
Jdk7以后出现另一种方式处理多个异常
  try{
   可能出现问题的代码;
  }catch(异常类名1 | 异常类名2 |... 对象名){
    处理异常
  }
package Exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo3 {
public static void main(String[] args) {
	int a=1;
	int b=0;
	String str="2018-5-20";
	try {
		System.out.println(a/b);
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd-hh");
		Date d=sdf.parse(str);
		System.out.println(d);
		//这多个异常类属于同一个级别
	}catch(ArithmeticException | ParseException e) {
		System.out.println("程序有问题");
		e.printStackTrace();
	}
}
  
}

编译时期异常和运行时期异常的区别?
 
  编译时期:开发者必须进行显示处理,不处理,编译不能通过,
   运行时期异常:无需进行显示处理,可以像编译时期一样进行处理 
  处理异常的第二种方式:使用throws 抛出异常 (跟在方法的后面)
  xxx 返回值  方法名() throws  异常类名{
  }

package Exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo4 {
 public static void main(String[] args) throws ParseException {
	
	// method2();
	 method1();
}
 public static void method1() throws ParseException {
	 String str="1996-2-4";
	 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		Date d=sdf.parse(str);
		System.out.println(d);	
 }
 public static void method2()throws ArithmeticException {
	 int a=1;
	 int b=0;
	 System.out.println(a/b);
 }
}

标准格式 try{ ... }catch(异常类 对象){ // 异常处理 } 执行try里面的代码
  如果出现了问题,它会通过代码的问题创建一个异常对象,然后通过异常对象和catch里面的异常类是否一致
 如果一致的情况,就会出现catch里面的代码,执行Throwable里面的方法

 public String getMessage() :消息字符串

  public String toString(): 异常的简短描述 ": ":由冒号和空格组成

 public void printStackTrace():返回值void 直接调用, 包含了消息字符串,还有": "信息描述,具体出现异常的代码定位以及定位的源码上

package Exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo5 {
public static void main(String[] args) {
	String str="2018-5-21";
	try {
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
	Date d=sdf.parse(str);
	System.out.println(d);
	System.exit(0);//在Java中执行finally语句之前jvm终止,才不会执行finally
	System.out.println(d);
	}catch(ParseException e) {
		System.out.println(e.toString());
	    System.out.println("-------");
		System.out.println(e.getMessage());
		System.out.println("-----------");
		e.printStackTrace();	
	}finally {
		System.out.println("会不会执行呢");
	}
}
}
throw:表示也是抛出异常,抛出的一个异常对象 (throw new 异常类名() :匿名对象的方式)
 面试题:
  throws和throw的区别?
  throws:也是表示抛出异常,它后面跟的异常类名,并且可以多个异常类名中间逗号开
  举例:
  public void show() throws IoException,ClassNotFoundException{...}
  在方法上抛出,由调用者处理
  它表示抛出异常的可能性
  throw:抛出的一个异常对象
  在语句体中抛出的,由语句体进行处理

  它表示抛出异常的肯定性

package Exception;

public class ExceptionDemo6 {
public static void main(String[] args) {
	try {
	method();
	}catch(Exception e) {
		System.out.println("出异常了");
		e.printStackTrace();
	}
}
public static void method() {
	int []arr= {1,2,3,4,5};
	for(int i=0;i<7;i++) {
		if(i>=arr.length)
			throw new ArrayIndexOutOfBoundsException();
		System.out.println(arr[i]);
	}
} 
}

try...catch...finally
finally语句体是一定会执行的,除非是Jvm退出了 
 面试题:
  如果catch里面有return 语句,finally中的代码还会执行,是在return语句之前执行还是return后执行?

  finally中代码是一定会执行的,是在return前

package Exception;

public class ExceptionDemo7 {
public static void main(String[] args) {
System.out.println(get());
System.out.println(get2());
}
public static int get() {
	int x = 0;
	  try {
		  
		  int a=1;
		  int b=0;
		  System.out.println(a/b);
	  }catch(Exception e) {
		 // e.printStackTrace();
		   x=10;
		  return x;
			/**
			 * try的代码出现问题了,执行catch中的语句,30赋值a,
			 * return 30(已经形成了一个回路径)finally代码一定会执行(除非Jvm) a = 40 ,在fianlly外面
			 * 有return a: a记录回路径的那个a,返回30
			 */

	  }finally {
		  x=20;
	  }
     return x;
}

public static int get2() {
	int x = 0;
	  try {
		  
		  int a=1;
		  int b=0;
		  System.out.println(a/b);
	  }catch(Exception e) {
		 // e.printStackTrace();
		   x=10;
		 // return x;
	  }finally {
		  x=20;
		  return x;
	  }
	  
}

}
自定义异常类,两种方式
  1)自定义一个类,这个继承自Exception
  2)继承RuntimeException 
public class MyException extends Exception {

	public MyException() {
		super();
	}

	public MyException(String message) {
		super(message) ;
	}
}

自定义一个异常类

package Exception;

public class Student {
public void infer(int examation) throws Exception {
	//判断成绩的方法
	if(examation<0||examation>100)
		throw new Exception("输入的成绩有问题");
	else System.out.println("这个成绩还行");
}
}
package Exception;

import java.util.Scanner;

public class ExceptionDemo8 {
public static void main(String[] args) throws Exception {
	//创建键盘录入对象
	System.out.println("请输入一个成绩");
	Scanner sc=new Scanner(System.in);
	//创建Student对象
	Student s=new Student();
	int examation=sc.nextInt();
	//调方法
	s.infer(examation);
}
}

异常中的注意事项:
  子类继承父类的时候的注意事项 
  1)子类重写父类的方法的时候,子类的方法的抛出的异常必须要么是父类的方法异常一样,要么是父类方法异常的子类

  2)子类重写父类方法的时候,如果父类中的这个方法没有抛出异常,那么子类重写的这个方法也不能抛出异常,只能try...catch

package Exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo9 {
	public static void main(String[] args) throws Exception {
		Fu f = new Zi();
		f.method();
		f.show();
	}

}

class Fu {
	public void show() throws Exception {
	}

	public void method() {
	}
}

class Zi extends Fu {

	public void show() throws ArrayIndexOutOfBoundsException {
		int[] arr = { 1 };
		int i = 2;
		if (i >= 1)
			throw new ArrayIndexOutOfBoundsException("数组角标应该越界了");
		else
			System.out.println(arr[i]);
	}

	public void method() {
		try {
			String str = "2222-12-22";
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh");
			Date d = sdf.parse(str);
		} catch (ParseException e) {
			System.out.println("应该出问题了");
			e.printStackTrace();
		}
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值