需求:有很多学生,学生有姓名,有学号,怎样根据学生的学号查找学生?
之前学习的集合,可以将姓名,学号作为学生类的中两个成员变量,创建集合的时候存储这个类型
关键只知道学生学号,通过学号找姓名
Key Value
学号1 姓名1
学号2 姓名2
学号3 姓名3
学号1(重复的键) 姓名4
Java针对这种情况采取了一种技术----->Map集合 ,键值的映射关系的一种集合(接口)
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
Map
Map接口的子实现类:
HashMap和TreeMap
Map接口的功能:
添加功能:
V put ( K key,V value ) :将指定的值和键关联起来
如果当前的这个键是一次存储,则返回值null
如果不是第一次存储,返回值是第一次对应的值,当前的值就把之前的键对应的值替换掉!
获取功能
Set
> entrySet() :和Map集合的遍历有关系(键值对对象)Set
keySet() :获取映射关系中所有的键的集合int size()返回此映射中的键-值映射关系数
删除功能
void clear():删除所有映射关系
Vremove(Object key)如果存在一个键的映射关系,则将其从此映射中移除
判断功能:
boolean containsKey(Object key)如果此映射包含指定键的映射关系,则返回 true
boolean containsValue(Object value):映射关系中是否包含指定的值
boolean isEmpty():判断映射关系是否为空
import java.util.HashMap; import java.util.Map;; public class MapDemo1 { public static void main(String[] args) { Map
m=new HashMap<>(); System.out.println(m.put("23", "zhangsan")); //添加元素 m.put("高圆圆", "赵又廷") ; m.put("周杰伦", "昆凌") ; m.put("黄晓明", "babay") ; m.put("文章", "马伊琍") ; System.out.println(m.containsKey("高圆圆")); System.out.println(m.containsKey("赵又廷")); System.out.println(m.containsKey("杨过")); System.out.println(m.containsValue("马伊琍")); System.out.println(m.isEmpty()); System.out.println(m.remove("周杰伦")); System.out.println(m.size()); System.out.println(m); } }
Map集合的遍历(一)
Set
keySet() :获取映射关系中所有的键的集合V get(Object key):通过键找值
转换法:
这种遍历方式实际开发中经常用的...
思路:
1)获取所有的键的集合
2)通过键找它对应的值
3)遍历即可
import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo2 { public static void main(String[] args) { Map
m=new HashMap(); m.put("杨过", "小龙女") ; m.put("郭靖", "黄蓉") ; m.put("陈旋风", "梅超风") ; m.put("高圆圆", "赵又廷") ; Set set=m.keySet(); for(String s:set) { String ss=m.get(s); System.out.println(s+"="+ss); } } }
Map集合的遍历 (二)
Set
> entrySet() : 和Map集合的遍历有关系(键值对对象)转发法:
1)获取所有的结婚证
2)通过结婚证分别找对应的丈夫和妻子
3)遍历输出
思路:
1)获取所有的键值对象entrySet()
2) K getKey() 和 v getValue(),获取键值对对象中的每个键和每个值
3)遍历
import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo3 { public static void main(String[] args) { Map
m=new HashMap(); m.put("杨过", "小龙女"); m.put("郭靖", "黄蓉"); m.put("陈旋风", "梅超风"); m.put("高圆圆", "赵又廷"); Set > entry=m.entrySet(); for(Map.Entry kv:entry) { String key=kv.getKey(); String value=kv.getValue(); System.out.println(key+"="+value); } } } HashMap
HashMap集合本身基于哈希表
它可以保证键的唯一性(Map都是针对键有效)
HashMap
HashMap底层哈希表
哈希表:依赖于两个方法 hashCode() ,equals()方法
线程安全的类:
StringBuffer :字符串缓冲区
Vector :List集合
Hashtable :Map集合的
import java.util.HashMap; import java.util.Set; public class HashMapDemo1 { public static void main(String[] args) { HashMap
map=new HashMap(); map.put("it001", "马云") ; map.put("it003", "马化腾") ; map.put("it004", "乔布斯") ; map.put("it001", "裘伯君"); map.put("it005", "比尔盖茨"); Set set = map.keySet(); for(String s:set) { System.out.println(s+"---"+map.get(s)); } } } LinkedHashMap
LinkedHashMap
:是Map接口基于哈希表和链接列表实现的
哈希表保证键的唯一性
链接列表保证元素有序性(存储和取出一致)
import java.util.LinkedHashMap; import java.util.Set; public class LInkedHashDemo1 { public static void main(String[] args) { LinkedHashMap
map=new LinkedHashMap(); map.put("it001", "hello"); map.put("it002", "mysql"); map.put("it003", "world"); map.put("it004", "javaweb"); map.put("it001", "javaee"); Set set = map.keySet(); for(String s:set) { String ss=map.get(s); System.out.println(s+"---"+ss); } } }
TreeMap
TreeMap基于红黑树结构的Map接口的实现
TreeMap存储自定义类型
TreeMap
public class TreeMapDemo2 { public static void main(String[] args) { TreeMap
tm=new TreeMap(new Comparator () { @Override public int compare(Student s1, Student s2) { int num=s1.getAge()-s2.getAge(); return num; } });
需求:
字符串:比如: aaaaabbbbcccddddee ,最终控制台要出现的结果:a(5)b(4)c(3)d(3)e(2)
思路:
1)改进:键盘录入一个字符串
2)创建一个HashMap集合key:Character,Value:Integer
3)将录入的字符串转换成字符数组
4)遍历可以获取每一个字符
5)将元素添加到对应的HashMap集合中
使用的put(key,value): 通过判断值是否null ,如果是null表示第一次存储
集合对象.put(ch,1) ;
否则,不是null
Integer那个值++;
集合对象.put(ch,变量Integer值) ;
6)遍历HashMap集合即可
import java.util.HashMap; import java.util.Scanner; import java.util.Set; public class 统计字符个数 { @SuppressWarnings("unused") public static void main(String[] args) { HashMap
map=new HashMap(); Scanner in =new Scanner(System.in); System.out.println("请输入您要统计的字符串:"); String str=in.next(); char[] ch=str.toCharArray(); for(Character c:ch) { Integer i=map.get(c); if(i==null) { map.put(c, 1); }else { i++; map.put(c, i); } } Set set = map.keySet(); StringBuilder sb=new StringBuilder(); for(Character ccc:set) { Integer i=map.get(ccc); sb.append(ccc).append("(").append(i).append(")"); } String s=new String(sb); System.out.println(s); } }
Collections
Collection和Collections的区别:
Collection:顶层次单列集合的根接口,它是一个集合,是一个接口
Collections:是针对集合操作的工具类,有一些功能:随机置换,集合里面的二分查找,将集合的元素进行反转
Collections常用方法:
public static
int binarySearch(List list, T key) 集合的二分查找 static T max(Collection coll):获取集合中的最大值
public static void reverse(List> list):将集合中的元素顺序反转
public static void shuffle(List> list):将集合中的元素打乱
public static void sort(List
list):排序 Collections.sort(list, new Comparator
() { @Override public int compare(Student s1, Student s2) { int num= s1.getAge()-s2.getAge(); int num2= num==0 ?s1.getName().compareTo(s2.getName()) :num ; return num2; } });
set集合
Set集合和List集合的区别?
Set集合:不允许元素重复,唯一的(元素可以为null) ,不能保证迭代的顺序恒久不变(底层是哈希表和hascode)
无序(存储和取出不一致)
List集合:允许元素重复,并且存储特点:有序性(存储和取出一致)
用Set集合存储元素并遍历
发现Set集合存储元素的时候,可以保证元素的唯一性,原因什么?
看源码:
HashSet集合的add方法底层依赖于双列集合HashMap,它依赖于两个方法,HashCode()方法和equals()方法
先比较字符串的HashCode()码值一样,再比较equals()方法
如果hasCode码值一样,还要比较内容是否相同,由于存储String,重写了equals()方法
String本身重写了equals方法,所以不需要再重写了!
用Set集合存储自定义对象遍历
现在是自定义的类,HashSet集合的add()方法本身依赖于hashCode()和equals()方法
在Student类中并没重写这两个方法,
解决办法:重写这两个方法
如果在开发中,要保证元素的唯一性,并且还要保证元素有序(存储和取出一致),使用LinkedHashSet集合
LinkedHashSet集合:
底层是一种链接列表和哈希表组成
可以保证元素的唯一性,是由哈希表决定的(hashCode()和equals())
可以保证元素的迭代顺序一致(有序),存储和取出一致,是由链表决定
import java.util.LinkedHashSet;
public class LinkedHashSetDemo1 {
public static void main(String[] args) {
LinkedHashSet link=new LinkedHashSet();
link.add("hello") ;
link.add("java") ;
link.add("world") ;
link.add("world") ;
link.add("world") ;
link.add("java") ;
for(String s:link) {
System.out.println( s);
}
}
}
如果开发中要使用集合排序的问题,使用TreeSet集合(红黑树结构)
TreeSet:
可以保证元素唯一并且元素排序(Integer类型的元素自然升序)
1)自然排序
2)选择器排序
对于自定义的类型,要实现自然排序,自定义的类型必须实现Comparable接口中的方法,compareTo() :比较方法
TreeSet集合模拟情况下是通过自然顺序对集合中的元素排序
给TreeSet集合存储以下元素:20,23,22,18,17,19,24..
import java.util.TreeSet;
public class TreeSetDemo1 {
public static void main(String[] args) {
TreeSet ts=new TreeSet();
ts.add(20) ; //add()方法底层的源码是一个Map接口实例
ts.add(22) ;
ts.add(18) ;
ts.add(23) ;
ts.add(24) ;
ts.add(17) ;
ts.add(19) ;
ts.add(18) ;
ts.add(24) ;
for(Integer i:ts) {
System.out.println(i);
}
}
}
需求:使用TreeSet集合存储自定义对象(Student类型),并遍历!
如何排序?
按照学生的年龄从小到大进行排序 (主要条件)
唯一性:
如果成员变量的值一样认为是同一个对象
import java.util.Comparator; //自定义类,该类实现Comparator保证集合中的元素进行比较器排序 public class MyComparator implements Comparator
{ @Override public int compare(Student s1, Student s2) { / 自然排序:Comparable 里面compareTo(Student s) this---->s1 s---s / //return 0; //按照姓名长度进行比较 int num = s1.getName().length() - s2.getName().length() ; //长度一样,还要比较姓名的内容是否相同 int num2 = num==0 ?s1.getName().compareTo(s2.getName()) : num ; //最终看年龄是否一致 int num3 = num2 ==0 ? (s1.getAge() - s2.getAge()) : num2 ; return num3 ; } }
TreeSet集合的构造方式不同,使用的排序也不同
自然排序:自定义的类实现Compareable接口,然后创建TreeSet对象,通过无参构造形式创建对象
比较器排序 :public TreeSet(Comparator
comparator) 两种方式:
1)自定义一个类,该类实现Comparator接口,重写Comparator接口中的compare()方法
2)直接使用接口匿名内部类的方式实现
TreeSet集合保证元素唯一,是看返回值是否为0
比较器排序:
TreeSet
ts=new TreeSet(new Comparator () { @Override public int compare(Student4 s1, Student4 s2) { int num1=s1.getName().length()-s2.getName().length(); int num2=num1==0?s1.getName().compareTo(s2.getName()):num1; int num3=num2==0?s1.getAge()-s2.getAge():num2; return num3; } }); HashMap
HashMap集合本身基于哈希表
它可以保证键的唯一性(Map都是针对键有效)
HashMap
HashMap底层哈希表
哈希表:依赖于两个方法 hashCode() ,equals()方法
LinkedHashMap:是Map接口基于哈希表和链接列表实现的
哈希表保证键的唯一性
链接列表保证元素有序性(存储和取出一致)
TreeMap基于红黑树结构的Map接口的实现
TreeMap存储自定义类型
TreeMap
主要条件:年龄从小到大
面试题:
HashMap集合和Hashtable的区别?
共同点:都是map接口的实现类,都是基于哈希表的实现类
HashMap集合线程不安全的类,不同步,执行效率高(允许键和值是null的)
Hashtable集合线程安全的类,同步,执行效率低(不允许有null键和null值)
线程安全的类:
StringBuffer :字符串缓冲区
Vector :List集合
Hashtable :Map集合的
/
需求:
字符串:比如: aaaaabbbbcccddddee ,最终控制台要出现的结果:a(5)b(4)c(3)d(3)e(2)
思路:
1)改进:键盘录入一个字符串
2)创建一个HashMap集合key:Character,Value:Integer
3)将录入的字符串转换成字符数组
4)遍历可以获取每一个字符
5)将元素添加到对应的HashMap集合中
使用的put(key,value): 通过判断值是否null ,如果是null表示第一次存储
集合对象.put(ch,1) ;
否则,不是null
Integer那个值++;
集合对象.put(ch,变量Integer值) ;
6)遍历HashMap集合即可
Collection和Collections的区别:
Collection:顶层次单列集合的根接口,它是一个集合,是一个接口
Collections:是针对集合操作的工具类,有一些功能:随机置换,集合里面的二分查找,将集合的元素进行反转
集合的二分查找
public staticint binarySearch(List list, T key)
static T max(Collection coll):获取集合中的最大值
public static void reverse(List> list):将集合中的元素顺序反转
public static void shuffle(List> list):将集合中的元素打乱
public static void sort(Listlist)
集合本身基于哈希表它可以保证键的唯一性(Map都是针对键有效)
HashMap
String:人的ID编号
String:人的姓名
HashMap
Integer:年龄
String:姓名
/
HashMap
String:学号
Student:学号对应一个学生:有姓名和年龄
HashMap键:是一种自定义类型
Student:学生:年龄和姓名
String:朝代
如果对象的成员变量值一样,认为同一个人.
HashMap底层哈希表
哈希表:依赖于两个方法 hashCode() ,equals()方法
LinkedHashMap:是Map接口基于哈希表和链接列表实现的
哈希表保证键的唯一性
链接列表保证元素有序性(存储和取出一致)
TreeMap基于红黑树结构的Map接口的实现
TreeMap存储自定义类型
TreeMap
主要条件:年龄从小到大
面试题:
HashMap集合和Hashtable的区别?
共同点:都是map接口的实现类,都是基于哈希表的实现类
HashMap集合线程不安全的类,不同步,执行效率高(允许键和值是null的)
Hashtable集合线程安全的类,同步,执行效率低(不允许有null键和null值)
线程安全的类:
StringBuffer :字符串缓冲区
Vector :List集合
Hashtable :Map集合的
/
需求:
字符串:比如: aaaaabbbbcccddddee ,最终控制台要出现的结果:a(5)b(4)c(3)d(3)e(2)
思路:
1)改进:键盘录入一个字符串
2)创建一个HashMap集合key:Character,Value:Integer
3)将录入的字符串转换成字符数组
4)遍历可以获取每一个字符
5)将元素添加到对应的HashMap集合中
使用的put(key,value): 通过判断值是否null ,如果是null表示第一次存储
集合对象.put(ch,1) ;
否则,不是null
Integer那个值++;
集合对象.put(ch,变量Integer值) ;
6)遍历HashMap集合即可
Collection和Collections的区别:
Collection:顶层次单列集合的根接口,它是一个集合,是一个接口
Collections:是针对集合操作的工具类,有一些功能:随机置换,集合里面的二分查找,将集合的元素进行反转
集合的二分查找
public staticint binarySearch(List list, T key)
static T max(Collection coll):获取集合中的最大值
public static void reverse(List> list):将集合中的元素顺序反转
public static void shuffle(List> list):将集合中的元素打乱
public static void sort(Listlist)