理解集合框架---map集合【3】

1.集合框架map介绍

map不属于Collection接口
map集合中存放的都是一组组映射关系(一对一) key=value
在线api查找map了解方法:
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

三个map集合中特别方法

1.put
2.entrySet 与keySet

这两个方法是map集合中所特有的遍历方法

map集合是不继承collection接口
这也就意味着它不具备迭代器的方法
1.1新增的用途

package com.myy.map;

import java.util.HashMap;
import java.util.Map;


/**
 * 三个map集合中特别的方法
 * 1.put
 *  新增的用途
 * 2.entrySet
 * 3.keySet
 * @author myy
 *
 */
public class MapDemo {
public static void main(String[] args) {
	Map map=new HashMap<>();
	map.put("zs", 15);
	map.put("ls", 20);
	map.put("ww", 18);
	map.put("zl", 23);
	map.put("xx", 45);
	System.out.println(map);
}

}

输出:
在这里插入图片描述
1.2修改用途(当容器已经存在了的key,再次存放,那么会覆盖原有的key所对应的值value)

public static void main(String[] args) {
	Map map=new HashMap<>();
	map.put("zs", 15);
	map.put("ls", 20);
	map.put("ww", 18);
	map.put("zl", 23);
	map.put("xx", 45);
	map.put("ls", 21);
	System.out.println(map);
}

输出:
在这里插入图片描述
1.3调用此方法,可以获取原来的的key对应的值
开发中的案例:
主播刷排名(map集合能做到把你替换前的值返回)

public static void main(String[] args) {
	Map map=new HashMap<>();
	map.put("zs", 15);
	map.put("ls", 20);
	map.put("ww", 18);
	map.put("zl", 23);
	map.put("xx", 45);
	Object old=map.put("ls", 21);
	System.out.println(old);
	System.out.println(map);
}

输出:
在这里插入图片描述
2.1 entrySet

public static void main(String[] args) {
	Map map=new HashMap<>();
	map.put("zs", 15);
	map.put("ls", 20);
	map.put("ww", 18);
	map.put("zl", 23);
	map.put("xx", 45);
	Object old=map.put("ls", 21);
	System.out.println(old);
	System.out.println(map);
	
	
	Set<Entry<Object, Object>>  entrySet=map.entrySet();
	for (Entry<Object, Object> entry : entrySet) {
		System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
	}
}

输出:
在这里插入图片描述

得出结论: HashMap是无序的,集合的底层是set集合做的

2.2 KeySet

package com.myy.map;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;


/**
 * 三个map集合中特别的方法
 * 1.put
 *  新增的用途
 *  修改用途(当容器已经存在了的key,再次存放,那么会覆盖原有的key所对应的值value)
 *  调用次方法,可以获取原来的的key对应的值
 *    开发中的案例:
 *    主播刷排名(map集合能做到把你替换前的值返回)
 * 2.entrySet
 * 3.keySet
 *      这两个方法是map集合中所特有的遍历方法
 *      
 *  HashMap是无序的,集合的底层是set集合做的   
 *      
 *  map集合是不继承collection接口
 *     这也就意味着它不具备迭代器的方法  
 *    
 * @author myy
 *
 */
public class MapDemo {
public static void main(String[] args) {
	Map map=new HashMap<>();
	map.put("zs", 15);
	map.put("ls", 20);
	map.put("ww", 18);
	map.put("zl", 23);
	map.put("xx", 45);
	Object old=map.put("ls", 21);
	System.out.println(old);
	System.out.println(map);
	
	
	/*Set<Entry<Object, Object>>  entrySet=map.entrySet();
	for (Entry<Object, Object> entry : entrySet) {
		System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
	}*/
	Set<Object> KeySet=map.keySet();
	for (Object key : KeySet) {
		System.out.println("key:"+key+",value:"+map.get(key));
	}
}

}

输出:
在这里插入图片描述

小结:
Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合石线程同步的,jdk1.0,效率低
HashMap:底层是哈希表数据结构,允许使用null值和null键,该集合是不同步的。将Hashtable替代;jdk1.2,效率高
TreeMap:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序
能够进行自然排序以及比较器排序
注意:
添加元素时,如果键已经在集合中存在,那么后添加的值会覆盖原来的值,并且put方法会将原有的值返回

集合框架Map应用

应用一:

①将学生作为键,地址作为值进行存储,名字年龄相同则被认定为一个人,最后输出
②最后按年龄进行排序
③需求改变、按姓名进行排序
思路分析:
第一点:
a.封装学生类
b.判断重复(hashCode/equals)
c.打印

package com.myy.map;

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

/**
 * 应用一:
 * 1、将学生作为键,地址作为值进行存储,名字年龄相同则被认定为一个人,最后输出
 *  思路:
 *    a.封装学生类
 *    b.判断重复(hashCode/equals)
 *    c.打印
 * 2、最后按年龄进行排序
 * 3、需求改变、按姓名进行排序
 *    
 * @author myy
 *
 */
public class HashMapDemo {
public static void main(String[] args) {
	HashMap map=new HashMap<>();
	map.put(new Student("zs", 20), "hunan");
	map.put(new Student("ls", 25), "shaoyang");
	map.put(new Student("ww", 18), "henan");
	map.put(new Student("zl", 20), "hebei");
	map.put(new Student("ls", 20), "shaodong");
	map.put(new Student("ls", 20), "shaobei");
	
	Set keySet=map.keySet();
	for (Object key : keySet) {
		System.out.println(key);
	}

}
}
class Student{
	private String name;
	private int 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;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Student() {
		super();
	}
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	public int hashCode() {
		return this.name.hashCode()+this.age;
	}
	public boolean equals(Object obj) {
		Student stu=(Student) obj;
		return this.name.equals(stu.name) && this.age==stu.age;
	}
	
}

输出打印结果:
在这里插入图片描述

注意:hashCode/equals方法

第二点:
a.需要让学生类自身具备比较性,实现Comparable接口

package com.myy.map;

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

/**
 * 应用一:
 * 1、将学生作为键,地址作为值进行存储,名字年龄相同则被认定为一个人,最后输出
 *  思路:
 *    a.封装学生类
 *    b.判断重复(hashCode/equals)
 *    c.打印
 * 2、最后按年龄进行排序
 *    a.需要让学生类自身具备比较性,实现Comparable接口
 * 3、需求改变、按姓名进行排序
 *    
 * @author myy
 *
 */
public class HashMapDemo {
public static void main(String[] args) {
	HashMap map=new HashMap<>();
	map.put(new Student("zs", 20), "hunan");
	map.put(new Student("ls", 25), "shaoyang");
	map.put(new Student("ww", 18), "henan");
	map.put(new Student("zl", 20), "hebei");
	map.put(new Student("ls", 20), "shaodong");
	map.put(new Student("ls", 20), "shaobei");
	
	Set keySet=map.keySet();
	for (Object key : keySet) {
		System.out.println(key);
	}

}
}
class Student implements Comparable<Student>{
	private String name;
	private int 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;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Student() {
		super();
	}
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	public int hashCode() {
		return this.name.hashCode()+this.age;
	}
	public boolean equals(Object obj) {
		Student stu=(Student) obj;
		return this.name.equals(stu.name) && this.age==stu.age;
	}
	@Override
	public int compareTo(Student o) {
		int num=this.age-o.age;
		if(num==0) {
			this.name.compareTo(o.name);
		}
		return num;
	}
	
}

输出:
在这里插入图片描述

注意:比完了主要条件再比次要条件

第三步:
改变代码是不可取的,我们需要新增一个比较器来完成需求
实现java.util.comparator

package com.myy.map;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeMap;

/**
 * 应用一:
 * 1、将学生作为键,地址作为值进行存储,名字年龄相同则被认定为一个人,最后输出
 *  思路:
 *    a.封装学生类
 *    b.判断重复(hashCode/equals)
 *    c.打印
 * 2、最后按年龄进行排序
 *    a.需要让学生类自身具备比较性,实现Comparable接口
 * 3、需求改变、按姓名进行排序
 *    改变代码是不可取的,我们需要新增一个比较器来完成需求
 *    实现java.util.comparator
 *    
 * @author myy
 *
 */
public class HashMapDemo {
public static void main(String[] args) {
	//HashMap map=new HashMap<>();
	TreeMap map=new TreeMap<>(new StuNameComp());
	map.put(new Student("zs", 20), "hunan");
	map.put(new Student("ls", 25), "shaoyang");
	map.put(new Student("ww", 18), "henan");
	map.put(new Student("zl", 20), "hebei");
	map.put(new Student("ls", 20), "shaodong");
	map.put(new Student("ls", 20), "shaobei");
	
	Set keySet=map.keySet();
	for (Object key : keySet) {
		System.out.println(key);
	}

}
}
class StuNameComp implements Comparator<Student>{

	public int compare(Student o1, Student o2) {
		int num=o1.getName().compareTo(o2.getName());
		if(num==0) {
			return o1.getAge()-o2.getAge();
		}
		return num;
	}
	
}

class Student implements Comparable<Student>{
	private String name;
	private int 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;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Student() {
		super();
	}
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	public int hashCode() {
		return this.name.hashCode()+this.age;
	}
	public boolean equals(Object obj) {
		Student stu=(Student) obj;
		return this.name.equals(stu.name) && this.age==stu.age;
	}
	@Override
	public int compareTo(Student o) {
		int num=this.age-o.age;
		if(num==0) {
			this.name.compareTo(o.name);
		}
		return num;
	}
	
}

输出:
在这里插入图片描述

String,StringBuffer,StringBuilder三者区别?

/*
 * String,StringBuffer,StringBuilder三者区别?
 * String a=new String("abc");
 * String b="abc";
 * a+="de";
 * StringBuffer sb1=new StringBuffer("abc");
 * StringBuilder sb2=new StringBuilder("abc");
 * sb1.append("de");
 * sb2.append("de");
 */
 StringBuilder sb=new StringBuilder("abc");

(1)a和b创建方式有什么区别,在内存是怎么分配的
画图分析:
在这里插入图片描述

结论:
a开辟两个空间
b开辟一个空间

(2)String b="abc"; a+="de";
这两行代码在内存中开辟了几个空间
在这里插入图片描述

得出结论:开辟了两个空间
字符串是一个常量。字符串比较特殊,每个字符串对应一个空间。

(3)该种写法问题
在这里插入图片描述

得出结论:每加一次会新增一个对象,耗内存。

(4)StringBuffer和StringBuilder与String区别

/*
 * String,StringBuffer,StringBuilder三者区别?
 * String a=new String("abc");
 * String b="abc";
 * a+="de";
 * StringBuffer sb1=new StringBuffer("abc");
 * StringBuilder sb2=new StringBuilder("abc");
 * sb1.append("de");
 * sb2.append("de");
 */
	
StringBuilder sb=new StringBuilder("abc");
sb.append("de");
System.out.println(sb);

输出:
在这里插入图片描述
画图分析:
在这里插入图片描述

得出结论:
和(2)的写法一样,但和内存不一样。没有创建新的对象,一直使用的是内存的一个对象。
就性能而言比(2)要高很多。所以说在操作字符串的过程中就都使用StringBuffer和StringBuilder

(5)StringBuffer与StringBuilder 的区别
StringBuffer 同步(不支持多线程导致:安全)
StringBuilder 异步(支持多线程导致:不安全)就于操作字符串而已,操作效率更高

应用二:

思路分析如下代码演示:

package com.myy.map;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/**
 * 统计字符串中字符出现次数
 * ahdadqfwefrfrhaouwouhhnbbnbz
 * a(2)b(4)..z(1)
 * 1.分析结果得出结论,我们需要字符串a-z当做键key,将次数作为值value,
 *   也就是我们需要创建一个map集合来做这些事情
 * 2.需要将待处理的字符串转成字符数组,以便于获取map集合的key
 * 3.如果该字符(a)第一次出现的时候,就给a对应key映射值value赋值为1
 *   如果说该字符再次出现,那么就是value+1
 * 4.打印出a(2)b(4)..z(1)格式串
 *   意味着需要对Key进行排序
 *   
 * @author myy
 *
 */
public class TreeMapDemo {
 public static void main(String[] args) {
	 String str="ahdadqfwfrfrhaouwouhhnbbnbz";
	//Map<Character, Integer> map=new HashMap<>();
	 Map<Character, Integer> map=new TreeMap<>();
	char [] charArray=str.toCharArray();
	for (char c : charArray) {
		Integer obj=map.get(c);
		if(obj==null) {
			//之前没有出现过,这是第一次出现
			map.put(c,1);
		}else {
			//之前这个字符已经出现过
			map.put(c, ++obj);
		}
	}
/*
 * String,StringBuffer,StringBuilder三者区别?
 * String a=new String("abc");
 * String b="abc";
 * a+="de";
 * StringBuffer sb1=new StringBuffer("abc");
 * StringBuilder sb2=new StringBuilder("abc");
 * sb1.append("de");
 * sb2.append("de");
 */
	
	StringBuilder sb=new StringBuilder();
	Set<Entry<Character, Integer>> entrySet=map.entrySet();
	for (Entry<Character, Integer> entry : entrySet) {
		sb.append(entry.getKey()+"("+entry.getValue()+")");
	}
	System.out.println(sb);
}
}

输出:
在这里插入图片描述

3.集合框架工具类(Collections、Arrays)

package com.myy.map;

import java.util.Arrays;

/**
 * 集合框架工具类(Collections、Arrays)
 * @author myy
 *
 */
public class UtilDemo {
public static void main(String[] args) {
	int arr[]= {32,453,333,234};
	System.out.println(arr);//打印[I@7852e922,无法打印内容
	//二分搜索法/冒泡排序/选择排序/快速排序/希尔排序
	System.out.println(Arrays.toString(arr));
}
}

输出:
在这里插入图片描述

得出结论:
Arrays提供了操作数组的快捷结构

Collections

package com.myy.set;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {
 public static void main(String[] args) {
	//TreeSet set=new TreeSet<>();
	//TreeSet<Person> set=new TreeSet<>(new PersonMoneyAgeComp());
	 TreeSet<Person> set=new TreeSet<>(Collections.reverseOrder(new PersonMoneyAgeComp()));
	set.add(new Person("zhangsan", 16, 1300) );
	set.add(new Person("wanwu",18,1500));
	set.add(new Person("lisi",23,2000));
	set.add(new Person("wanmazi",22,3500));
	set.add(new Person("liting",23,4300));
	// System.out.println(set);
	
	 Iterator it=set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
	}
		
//		Person [name=liting, age=23, money=4300]
//				Person [name=wanmazi, age=22, money=3500]
//				Person [name=lisi, age=23, money=2000]
//				Person [name=wanwu, age=18, money=1500]
//				Person [name=zhangsan, age=16, money=1300]
}
}
/**
 * 有钱并且年轻
 * @author myy
 *
 */
class PersonMoneyAgeComp implements Comparator<Person>{

	public int compare(Person o1, Person o2) {
		int num=o2.getMoney()-o1.getMoney();
		if(num==0) {
			return o1.getAge()-o2.getAge();
		}
		return num;
	}
	
}



class Person implements Comparable<Person>{
	private String name;
	private int age;
	private int money;
	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;
	}
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
	}
	public Person(String name, int age, int money) {
		super();
		this.name = name;
		this.age = age;
		this.money = money;
	}
	public Person() {
		super();
	}
	
	public int hashCode() {
		System.out.println("hashCode---"+this.name);
		int code=this.name.hashCode()+this.age;
		System.out.println(code);
		return code;
	}
	
	public boolean equals(Object obj) {
		Person p=(Person) obj;
		return this.name.equals(p.name) && this.age==p.age;
	}
	/**
	 * 让元素具有比较性
	 *注意:
	 *在做自然排序方法重写的时候,一定先判断主要条件、还要判断要条件
	 */
	public int compareTo(Person o) {
	  int num=o.money-this.money;
	  if(num==0) {
		return this.age-o.age;
	  }
	  return num;
	}
	
}

输出:

在这里插入图片描述

得出结论:
方便操作集合中的元素,工具类里封装操作集合的便捷方法

4、集合框架拓展(增强for循环、可变参数、静态导入)

(1)增强for循环

①是循环的一种
②格式:
for(集合里面存储的数据类型 变量名:被遍历的集合(Collection)/数组){
使用该变量即可,该变量其实就是数组或者集合中的元素
}
③特点:
a.对集合进行遍历
b.只能获取集合元素。但是不能对集合进行操作
C.迭代器除了遍历,还可以进行remove集合中元素的动作。
(如果是用ListIterator,还可以在遍历过程中对集合进行增删改查)

好处:简化了数组和集合的遍历
注意:该集合需要实现了iterable接口,比如Map集合就不行

传统for和高级for有什么区别?

代码演示:

package com.myy.map;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 
 * 
 * 对集合进行遍历
 * 只能获取集合元素。但是不能对集合进行操作
 * 
 * 迭代器除了遍历,还可以进行remove集合中元素的动作。
 * 如果是用ListIterator,还可以在遍历过程中对集合进行增删改查
 * 
 * 传统for和高级for有什么区别?
 * 高级for有一个局限性,必须有被遍历的目标。
 * 建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚本
 * @author myy
 *
 */
public class ForDemo {
	public static void main(String[] args) {
		ArrayList<String> al=new ArrayList<String>();
		al.add("ab");
		al.add("ls");
		al.add("ww");
		for (String s : al) {
			System.out.println(s);
		}
		System.out.println(al);
		
//		Iterator<String> it=al.iterator();
//		while(it.hasNext()) {
//			System.out.println("迭代器:"+it.next());
//		}
		int [] arr= {2,4,1};
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
		for (int a : arr) {
			System.out.println("a:"+a);
		}
		
		HashMap<Integer,String> hm=new HashMap<>();
		
		hm.put(1,"ls");
		hm.put(2,"ww");
		hm.put(3,"zl");
		Set<Integer> keySet=hm.keySet();
		for (Integer i : keySet) {
			System.out.println(i+"--"+hm.get(i));
		}
		
//		Set<Map.Entry<Integer, String>> entrySet=hm.entrySet();
//		for (Map.Entry<Integer, String> me : entrySet) {
//			System.out.println(me.getKey()+"--"+me.getValue());
//		}
		for (Map.Entry<Integer, String> me : hm.entrySet()) {
			System.out.println(me.getKey()+"--"+me.getValue());
		}
		
	}
  
  
}

输出:
在这里插入图片描述

得出结论:
高级for有一个局限性,必须有被遍历的目标。
弊端:增强for循环的目标不能为null.建议在使用前,先判断是否为null.
建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚本。

(2)可变参数

**①概述:**定义方法的时候,不知道该定义多少个参数
**②格式:**修饰符 返回值类型 方法名 (数据类型 变量名){}
代码演示:

package com.myy.map;

/**
 * JDK1.5版本的新特性
 * 
 * 方法的可变参数
 * 在使用时注意:可变参数一定要定义在参数列表最后面
 * @author myy
 *
 */
public class ParamMethodDemo {
	public static void main(String[] args) 
	{   
		//show(11,22);
        //虽然少定义了多个方法
		//但是每次都要定义一个数组。作为实际参数
		/*int [] arr= {11,22};
		show(arr);
		
		int [] arr1= {11,22,33,44};
		show(arr1);*/
		
		/*可变参数。
		其实就是上一种数组参数的简写形式。
		不用每一次都手动的建立数组对象。
		只要将要操作的元素作为参数传递即可。
		隐式将这些参数封装成了数组。*/
		
		show("hhh",2,3,4,5);

}
	//参数可传可不传,可变参数实际是个数组对象
	/*public static void show(int [] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}*/
	// 可变参数必须在形参后的最后一个  ,一个方法最多只有一个可变参数
		public static void show(String name,int... arr) {
			for (int i = 0; i < arr.length; i++) {
				System.out.println(arr[i]);
			}
			System.out.println("长度:"+arr.length);
		}
	
}

输出:
在这里插入图片描述

(3)静态导入

①格式:import static 包命.类名.静态成员
例如:import static java.util.Arrays.*
代码演示:

package com.myy.map;

/**
 * 当类名重名时,需要指定具体的包名
 * 当方法重名时,指定具备所属对象或者类
 * @author myy
 *
 */

import java.util.*;
import static  java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。

import static java.util.Collections.*;


import static  java.lang.System.*;//导入了System类中所有静态成员。

public class StaticDemo {
 public static void main(String[] args) {
	out.println("hhh");
	int [] arr= {3,2,4};
	
	sort(arr);
	int index=binarySearch(arr,1);
	out.print(Arrays.toString(arr));
	System.out.println("index:"+index);
	
	ArrayList al=new ArrayList<>();
	al.add(5);
	al.add(4);
	al.add(2);
	
	out.println(al);
	
	sort(al);
	out.println(al);
	
}
}

输出:
在这里插入图片描述

注意:a.类中的静态方法,就可以使用静态导入
b.如果要使用静态导入,为了防止在一个类中出现同名的方法,那么调用的时候需要前缀来区别开来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值