1.定义
Map集合是一个双列集合,以键值对的形式存在,将键和值捆绑到一起存放(Map.Entry(Entry中是Map类中的一个内部类))如果出现相同的键,会用新的值覆盖老的值,每个键最多只能映射到一个值
什么是键值对?
键值对就是有key-value组成的数据,一个key对应一个value,就像一个身份证号对应一个人一样,可以通过key寻value,所以map中存放的key只能是唯一。另外键值对称为entry
2.map的基本操作
package day23;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Example1 {
public static void main(String[] args) {
//1.添加数据
Map map=new HashMap();
Object put2=map.put(1001L, "xiaoming");
System.out.println(put2);
map.put(1002L,"xiohong");
System.out.println(map);
//如果key重复了,那么返回值是被覆盖的,旧的value
Object put=map.put("1001L","xiaowang");
System.out.println(map);
System.out.println(put);
//2.查询数据
//2.1根据键来获取的值
Object value=map.get(1001L);
System.err.println(value);
//2.1设置某个键的值
map.put(1001L, "xiaoli");
//2.2可以获得map中所有的键值对
Set entrySet=map.entrySet();
//2.2遍历Map中所有的entry==遍历Map中所有的key和value
}
}
上写代码中尽管添加数据和设置某个键的值的角度不同,但是操作相同
map和set集合具有相同之处,例如:hashset,hashset中含有map集合,hash
set对数据的操作实际上操作的是map中key的值,value则赋值为默认值。调用entrySet实际上,将map中entry中的地址赋值给Set集合,Set集合通过地址找到map中的entry
package day23;
import java.text.CollationElementIterator;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.plaf.synth.SynthOptionPaneUI;
//map的删除操作
public class Example5 {
public static void main(String[] args) {
//添加数据
Map map=new HashMap();
map.put(1001L, "小明");
map.put(1002L, "小红");
map.put(1003L, "小李");
map.put(1004L, "小王");
Object remove=map.remove(1004L);
System.out.println(remove);
System.out.println(map);
}
}
3.map集合的遍历
package day23;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
//Map集合的遍历==very重要
public class Example2 {
public static void main(String[] args) {
//添加数据
Map map=new HashMap();
map.put(1001L, "小明");
map.put(1002L, "小红");
map.put(1003L, "小李");
map.put(1004L, "小王");
//遍历map
//entrySet中存放的entry是Map集合中的内部类
Set entrySet=map.entrySet();
for(Object obj:entrySet) {
if(obj instanceof Map.Entry) {
Map.Entry entry=(Map.Entry)obj;
//获得entry中的键
Object key=entry.getKey();
//获得entry
Object value=entry.getValue();
System.out.println(key+"="+value);
}
}
}
}
package day23;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Example3 {
public static void main(String[] args) {
//添加数据
Map map=new HashMap();
map.put(1001L, "小明");
map.put(1002L, "小红");
map.put(1003L, "小李");
map.put(1004L, "小王");
//遍历map,遍历所有的key,遍历过程中根据key来获取值,实现遍历map
Set keyset=map.keySet();
Iterator iterator=keyset.iterator();
while(iterator.hasNext()) {
Object key=iterator.next();
Object value=map.get(key);
System.out.println(key+"="+value);
}
}
}
通过调用map集合中的KeySet方法。可以将map中所有键的地址赋值给Set,再通过这些地址,找到key。找到key值后。再通过key值找到value
package day23;
import java.text.CollationElementIterator;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.plaf.synth.SynthOptionPaneUI;
//方法三:collection value=map.values()
//直接获得Map中所有的value
public class Example4 {
public static void main(String[] args) {
//添加数据
Map map=new HashMap();
map.put(1001L, "小明");
map.put(1002L, "小红");
map.put(1003L, "小李");
map.put(1004L, "小王");
//遍历map,
Collection values=map.values();
for(Object object:values) {
System.out.println(object);
}
}
}
4.hashmap的介绍
底层使用的是数组
HashMap就是通过我们存入的key获取到一个hash值,经过计算之后,获取到一个数组角标,然后将key和value封装到一个Entry里面,然后存入数组
当数组容量不够的时候,会自动扩容一倍
当链表的长度大于8时,为提高效率,会将链表转换为红黑树
5.hashmap的带参数的构造器
HashMap(int inttalCapacity)
构造一个带有指定初始容量和默认加载因子(0.75)的空HashMap
6.使用HashCode方法的注意事项
package day23;
import java.util.HashMap;
import java.util.Map;
//HasMap怎么保持唯一
public class Example6 {
public static void main(String[] args) {
Map map=new HashMap();
Animal a1=new Animal();
a1.setName("小王");
a1.setAge(2);
Animal a2=new Animal();
a2.setName("小王");
a2.setAge(1);
map.put(a1, "动物1");
map.put(a1, "动物2");
//细节:调用HashMap的put方法时,会默认调用a1的HashMap方法,计算出在数据中的下标,两次都添加了
//a1,所以下标一样,则调用a1对象的equals方法,判断是否key一样
System.out.println(map);
//让属性完全相同的对象。被map视为是同一个对象,那么就需要重写HashCode
//目的就是让这样的对象,在一个链表。属性完全相同的两个对象的Hash
//Code值完全一样,同时,还需要重写equals方法,,再同一个链表中比较对象是否相同的依据是属性值
//是否一样
}
}
class Animal{
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;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Animal [name="+name+",age="+age+"]";
}
}
7.treeMap
存放在map集合中的元素可以被排序,所以在存储元素时,一定要告知treemap元素的排序方式
package day23;
import java.util.Comparator;
import java.util.TreeMap;
//要把数据存放到TreeMap,前提实现两种比较方法:
//-要么在构造器中创建一个比较器对象
//要么key的类实现Comparable
public class Example8 {
public static void main(String[] args) {
TreeMap map=new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
Worker w1=(Worker)o1;
Worker w2=(Worker)o2;
return (int)(w1.getId()-w2.getId());
}
});
Worker w1=new Worker(1001L, "laowang", 20);
Worker w2=new Worker(1001L, "laoli", 30);
map.put(w1, w1.getName());
map.put(w2, w2.getName());
}
}
class Worker{
private Long id;
private String name;
private int age;
public Worker(Long id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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 "Worker [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
package day23;
import java.util.Comparator;
import java.util.TreeMap;
//要把数据存放到TreeMap,前提实现两种比较方法:
//-要么在构造器中创建一个比较器对象
//要么key的类实现Comparable
public class Example9 {
public static void main(String[] args) {
TreeMap map=new TreeMap();
Worker w1=new Worker(1001L, "laowang", 20);
Worker w2=new Worker(1001L, "laoli", 30);
map.put(w1, w1.getName());
map.put(w2, w2.getName());
}
}
class Worker implements Comparable{
private Long id;
private String name;
private int age;
public Worker(Long id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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 "Worker [id=" + id + ", name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Worker w1=(Worker)o;
return (int)(this.id-w1.id);
//小的在前大的在后
}
}
7.泛型
7.1为什么要使用泛型
package generic;
import java.util.ArrayList;
import java.util.List;
//为什么使用泛型
//集合的特点是弥补了数组中的某个一个不足:数组中元素的数据类型必须是一致
//在开发中,更倾向于让集合只存一种数据类型。单一职原则
//通过使用泛型,约束集合中元素的数据类型。此时防止数据类型的多样化导致程序错误
public class Example1 {
public static void main(String[] args) {
List <Integer>list=new ArrayList<Integer>();
list.add(98);
list.add(99);
list.add(100);
//报错 list.add("良好");
}
}
7.2泛型的使用
package generic;
import java.util.ArrayList;
import java.util.List;
/**
* 泛型如何使用
* 只用在设计了泛型的类中,才能使用泛型
* 类要用泛型来解决什么样的问题
* 类中的泛型,相当于是占位符,在设计类是时没有指明某个类的属性的类型,但在使用类时,通过指明泛型类型,
* 于是类中占位符都变成了指定类型
* 在使用类时,如果不指明泛型类型,那么类中的占位符都变成了Object
* 如何声明和创建泛型类对象
* 声明时必须要指明泛型,且泛型只能是引用数据类型,不能使用基本数据类型,基本数据类型必须使用包装类
* 创建时也建议带上<>,jdk7以后,允许声明时指明了泛型,创建时,不指明泛型
* 类中设计多个泛型
* 如果要指明泛型,需要把类中设计的所有泛型都指明 有些不明确的类型可以使用Object。
* 或者都不指明
* 继承或实现有泛型类型的抽象类或接口该注意
* ——不指明父类的泛型类型,父类的泛型类型就是Object
class JavaStudent extends Student{}
* ——子类在继承父类时可以直接指明父类的泛型类型
* class JavaStudent extends Student<Integer>
* ——子类自己可以声明泛型类型来作为父类的泛型类型,把泛型确定的时机留给子类创建对象时
* class EnglishStudent<T> extends Student<T>{}子类中的T和父类中的T一样。
泛型方法,方法的返回值类型由方法的实参类型决定
泛型是编译时的约束,在运行是泛型起不到作用
*
* @author yu
*
*/
public class Example2 {
public static void main(String[] args) {
List list=new ArrayList();
Student<Object> stu1=new Student<>();
Student<Object>stu2=new Student<>();
Teacher t1=new Teacher<>();
Teacher <String ,Integer> t2=new Teacher<>();
EnglishStudent<Object> stu3=new EnglishStudent<>();
String object=A.getObject("hello");
}
}
class A{
public static <T> T getObject(T t) {
return t;
}
}
//
class EnglishStudent<T> extends Student<T>{
}
class JavaStudent extends Student<Integer>{
}
//在这个类中所有出现T的地方换成相应的类型
class Teacher<E,T>{
private T t;
private E e;
}
class Student<T>{
private String name;
private int age;
//运动特长
private T sport;
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 T getSport() {
return sport;
}
public void setSport(T sport) {
this.sport = sport;
}
}
7.3泛型在集合中的使用
package generic;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
public class Example3 {
public static void main(String[] args) {
TreeMap<Animal,String> t1=new TreeMap<Animal, String>();
Map<Long,String> map=new HashMap<>();
map.put(1001L, "xiaoming");
map.put(1002L, "xiaohong");
map.put(1003L, "xiaoli");
//遍历集合
Set<Entry<Long,String>> entrySet= map.entrySet();
// Iterator迭代的是Entry
Iterator<Entry<Long, String>> iterator=entrySet.iterator();
while(iterator.hasNext()) {
Entry<Long, String> entry=iterator.next();
Long key=entry.getKey();
String value=entry.getValue();
System.out.println(key+"="+value);
}
}
}
//comparable提供了一个比较依据<T>,与谁比较
class Animal implements Comparable<Animal>{
private String name;
private int age;
public Animal(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 int compareTo(Animal o) {
// TODO Auto-generated method stub
return 0;
}
}