Java日志七「Map,异常处理」

**

Map

**
上一篇文章主要提到了Collection集合以及它的实现类们,而Collection都是单列集合,也就是一个集合中储存的元素都是一个一个的。而Map是一个双列集合,集合中的元素是一对一对的存储的。

一个元素包含两个值(一个key一个value),数据类型可以相同也可以不同。key不可以重复,value可以重复,且一个key对应一个value。

Map集合有三种实现类:
1.HashMap集合是Map接口的一个实现类。底层是一个哈希表,所以它是无序的

2.HashTable集合也是Map接口的一个实现类,与HashMap很相似,不同之处在于HashTable不可以存储null值,null键

3.LinkedHashMap集合是HashMap的一个子类,底层是哈希表加一个链表,所以它是一个有序的集合

我们先在代码上看一下HashMap对象的创建和常用的方法:

Map<String,String> map=new HashMap<>();
		
		//Map接口常用方法
		
		//put方法:
		String v1=map.put("郑恺", "杨颖");//郑恺代表key值
		System.out.println("v1:"+v1);//key值不重复,返回null
		String v2=map.put("郑恺", "苗苗");
		System.out.println("v2:"+v2);//key值重复,返回被替换的value 
		System.out.println(map);
		
		System.out.println("==============");
		//remove:
		Map<String,Integer> map2=new HashMap<>();
		map2.put("赵丽颖",168);
		map2.put("林志玲",178);
		map2.put("迪丽热巴",170);
		System.out.println(map2);
		Integer i1=map2.remove("林志玲");//根据key来删除,返回其value
		System.out.println(i1);
		System.out.println(map2);
		
		System.out.println("==============");
		
		//get:
		Integer i=map2.get("迪丽热巴");//根据key来查找,返回其value
		System.out.println(i);
		System.out.println(map2);

结果

v1:null
v2:杨颖
{郑恺=苗苗}
==============
{林志玲=178, 赵丽颖=168, 迪丽热巴=170}
178
{赵丽颖=168, 迪丽热巴=170}
==============
170
{赵丽颖=168, 迪丽热巴=170}

通过上面的代码,我们更清晰的了解到Map集合中的元素,是成对存在的。一个元素就是key=value的格式。

下面我们来看一下Map集合的遍历(分为三步):

迭代器方法

//1.Map中的KeySet方法,把集合的key值取出来,储存到一个set集合中
	Set<String> set=map2.keySet();
		
	//2.通过迭代器遍历set集合:
	Iterator<String> it=set.iterator(); 
	while(it.hasNext()) 
	{
		String key=it.next();
		Integer value=map2.get(key);//3.再通过键找值
		System.out.println(key+"="+value);
	}
System.out.println();

增强for循环方法

//2.增强for循环:
for(String key:set) 
	{
		Integer value2=map2.get(key);//3.再通过键找值
		System.out.println(key+"="+value2);
	}

两种方式的结果

赵丽颖=168
迪丽热巴=170
赵丽颖=168
迪丽热巴=170

赵丽颖=168
迪丽热巴=170
赵丽颖=168
迪丽热巴=170

Map集合这样的双列集合让我们在统计与组合元素上方便了很多,下面是两个小练习,可以体会一下Map集合的妙用。

第一个练习:统计输入的字符个数,key存储字符,value存储数目。

	Scanner sc=new Scanner(System.in);
	System.out.println("请输入一个字符串:");
	String str=sc.next();
		
	HashMap<Character,Integer> hashmap=new HashMap<>();
	for(char c:str.toCharArray()) 
	{
		if(hashmap.containsKey(c)) 
		{
			Integer num=hashmap.get(c);
			num++;
			hashmap.put(c, num);
		}
		else
			hashmap.put(c, 1);
		}
		
	System.out.println(hashmap);

结果

请输入一个字符串:
asdasjkldhsadjnksahddndhasdhioawndjsbkadbuaisdj;asdk[admsdfhadjd
{a=11, b=2, d=15, f=1, h=5, i=2, j=5, k=4, l=1, m=1, n=3, o=1, s=9, u=1, w=1, ;=1, [=1}

第二个练习:做一个斗地主的小游戏,要求把三个人的牌与底牌打印出来,要求派牌的时候要随机,打印牌的时候由小到大。

//1.准备牌:
	HashMap<Integer,String> poker=new HashMap<>();//储存牌(包括数字和花色)
	ArrayList<Integer> poker_index=new ArrayList<>();//储存牌的索引
		
	List<String> colors=List.of("♥️","♠️","♣️","♦️");
	List<String> number=List.of("2","A","K","Q","J","10","9","8","7","6","5","4","3");
		
	int index=0;
	poker.put(index, "Joker");
	poker_index.add(index);
	index++;
	poker.put(index, "joker");
	poker_index.add(index);
	index++;
		
	for(String num:number) 
	{
		for(String col:colors) 
		{
			poker.put(index, col+num);
			index++;
			poker_index.add(index);
		}
	}
		
		
	//2.洗牌:
	Collections.shuffle(poker_index);
		
	//3.发牌:
	ArrayList<Integer> player01=new ArrayList<>();
	ArrayList<Integer> player02=new ArrayList<>();
	ArrayList<Integer> player03=new ArrayList<>();
	ArrayList<Integer> Last_card=new ArrayList<>();//底牌
		
	for(int i=0;i<poker_index.size();i++)
	{
		Integer in=poker_index.get(i);
		if(i>=51) 
		{//先发底牌
		Last_card.add(in);
		}
		else if(i%3==0) 
		{
			player01.add(in);
		}
		else if(i%3==1) 
		{
			player02.add(in);
		}
		else if(i%3==2) 
		{
			player03.add(in);
		}
	}
		
	//4.排序
	Collections.sort(player01);
	Collections.sort(player02);
	Collections.sort(player03);
	Collections.sort(Last_card);
		
				
	//5.看牌
	for(Integer key:Last_card) 
	{
		String value=poker.get(key);
		System.out.print(value);
			
	}
		
	System.out.println();
		
	for(Integer key:player01) 
	{
		String value=poker.get(key);
		System.out.print(value);
	}
		
	System.out.println();
		
	for(Integer key:player02) 
	{
		String value=poker.get(key);
		System.out.print(value);
	}
		
	System.out.println();
		
	for(Integer key:player03) 
	{
		String value=poker.get(key);
		System.out.print(value);
	}
		
	System.out.println();

结果

joker♦️Q♥️9
♣️A♦️A♥️K♥️Q♣️Q♥️J♦️J♥️10♣️9♥️8♣️8♥️7♥️6♦️4♠️3♣️3♥️2
Joker♠️2♥️A♠️A♣️K♠️Q♠️J♣️J♠️10♦️9♦️8♥️5♣️5♦️5♣️4♥️3♦️3
♣️2♦️2♠️K♦️K♣️10♦️10♠️9♠️8♠️7♣️7♦️7♠️6♣️6♦️6♠️5♥️4♠️4

通过上面两个小游戏我们可以更深入的理解Map集合。

**

Java的异常处理

**
Java有一个类叫Throwable,它是所有异常类的根类,所有的异常类都是由他继承。

而异常分为两种,一种是错误,一种是异常。

错误是不可以处理的,因为这是系统内部的错误,运行时报错。主要分为内存溢出和系统崩溃。

我们来看一个错误

int[] array=new int[1024*1024*1024];
//这是一个错误,内存溢出

结果

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at Error_and_Exception.Error_and_Exception_pricatice.main(Error_and_Exception_pricatice.java:43)

而异常是可以处理的,甚至有可以不处理的异常,比如RuntimeException以及它的子类都可以不处理。

下面是一个异常(传递的参数与自己定义的格式不相符)

	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM--dd");
	Date date=null;
	date=sdf.parse("2000--0513");

结果

java.text.ParseException: Unparseable date: "2000--0513"
	at java.base/java.text.DateFormat.parse(DateFormat.java:395)
	at Error_and_Exception.Error_and_Exception_pricatice.main(Error_and_Exception_pricatice.java:33)

在说如何处理这个异常的时候,我们先来看一下异常处理的过程:
1.JVM检测出异常,创建一个异常对象,包含了产生的(内容,原因,位置)

2.在出现异常的方法中若没有try catch语句,就抛给方法的调用者main

3.main中也没有try catch就把异常抛给main调用者JVM

4.JVM做两件事:
1.把这个异常对象以红色打印到控制台
2.中断处理

了解完过程,我们来看一下异常处理的两种方式:
1.throws
2.try catch

针对上面的异常案例,第一种处理方法

public static void main(String[] args) throws ParseException{
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM--dd");
	Date date=null;
	date=sdf.parse("2000--0513");
	}

这一种处理方式是把这个异常给抛出(throws),交给虚拟机处理,至于throws后面的语句是不同类型的异常,有很多种需要大家自己去了解,这里就不多说了。

第二种处理方法

public static void main(String[] args) {
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM--dd");
	Date date=null;
	try {
		date=sdf.parse("2000--0513");
	} catch (ParseException e) {
		e.printStackTrace();
		System.out.println("错误!");
	}
	finally //finally代码块是一定会执行的
	{
		System.out.println("这是finally代码块的代码");
	}
}

第二种处理方式就不把错误抛给虚拟机处理了,我们自己处理。try代码块里面写有可能出异常的代码,若真的发生了异常,catch就会捕获到然后执行catch代码块的代码。

第二种处理方式的结果

java.text.ParseException: Unparseable date: "2000--0513"
	at java.base/java.text.DateFormat.parse(DateFormat.java:395)
	at Error_and_Exception.Error_and_Exception_pricatice.main(Error_and_Exception_pricatice.java:33)
错误!
这是finally代码块的代码

最后我们来说一个throw关键字,它的作用是抛出一个异常(与throws不同,throw关键字必须写在方法内部,throws要写在方法头)

下面是代码展示throw的作用


public static void main(String[] args) throws  ArrayIndexOutOfBoundsException,NullPointerException {
		int[] array={1,2,3};
		method(array,3);

	}
	
	public static void method(int[] array,int index) throws ArrayIndexOutOfBoundsException,NullPointerException
	{
		if(index<0||index>array.length) 
		{
			throw new ArrayIndexOutOfBoundsException("索引异常");
		}
		if(array==null)
		{
			throw new NullPointerException("传递空数组");
		}
		
		System.out.println(array[index]);
	}

上面的代码在mian函数中调用了一个方法,参数传递了一个数组和一个用于数组索引的数字。考虑到这样的参数可能产生两种异常,一种是索引越界异常,一种是空指针异常(就是传递了一个空数组)。对应这两种情况,我们在写完判定条件后分别throw了ArrayIndexOutOfBoundsException(“索引异常”)与NullPointerException(“传递空数组”)。

下面是使用throw关键字的注意事项:
1.throw关键字必须写在方法的内部

2.throw关键字后new的对象必须是Exception或Exception的子类对象

3.throw关键字抛出后必须进行处理:

throw关键字后面创建的是RunTimeException或者RunTimeException的子类,我们可以不处理把它交给JVM

throw关键字后面的是创建编译异常,必须用throws或者try catch

4.若我们调用了一个可能产生异常的方法,例如下面的method方法,那么调用方法也必须throws该异常

5.若可能产生多个异常,我们也要抛出多个异常

这次就到这里,下次更新有关线程的知识

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值