1. map接口简介
- 实现map接口的类常用来存储键(key)-值(value)对;
- Map的底层实现是数组+链表(在数组中添加链表,用以减少遍历);
- 可以先定义一个链表数组(意思就是 每一个数组元素都是一个链表);
- map接口的实现类有HashMap、TreeMap和HashTable等;
- map类中存储的值由键来标识,就像是数据库的主键一样,不能重复;
- map中一般都是通过key寻找另一个对象;
- HashMap的效率高,但是安全性较低;HashTable效率低,但是安全度高;主要使用就是这两个类;HashTable的使用和HashMap相似;
2. HashMap中的重要方法说明:
以下就是所有重要的HashMap中的方法,
public class TestMap {
public static void main(String[] args) {
Map map1 = new HashMap();
map1.put("1", "545");
map1.put("455", "sdeed");
Map map = new HashMap();
map.put("dxs", "无奈");
map.put(new Integer(124), "测试");
map.put("dd","张的收");
map.put("测试remove",new Text(12) );
map.putAll(map1);//将所有的map1函数全部放到map里面;
// map.clear();将所有的元素全部删除;
//这里之所以需要进行转型是因为get出来的值是Object类型
//由于一般都要和泛型同时使用,没用泛型的话,默认就是object返回类型;
Text t = (Text)map.get("测试remove"); //将这个得到的对象赋值给t;
map.containsKey("dxs");//这是一个boolean类型的方法;用来查看对象里面是否有这个key值;
map.containsValue("sdf");//这是用来检测是否含有这个value值,同样也是boolean类型;
int x = map.size();//测试map的长度;这里结果是4
map.remove("测试remove");//观察remove是直接删除还是将数值移除出去,却并不删掉;
int y = map.size();//这里的答案是3,因为程序运行的顺序决定了结果;在这段代码前面移除了一个元素;
System.out.println(t.age);
System.out.println(y);
System.out.println(x);
System.out.println(map.get(124));
}
}
class Text{
public int age;
public Text(int age) {
this.age = age;
}
}
如果两个元素的键值(key)相同,那么在get时,会获取后一个元素的value;
准确点说就是map是通过键来取值,所以如果有两个键相同的值,那么后一个值就会覆盖前一个值;
下面程序是对map的基础存储架构进行一个更深层的理解;
public class MyMap {
private int size;//定义一个长度
MyLinkedList[] arr = new MyLinkedList[999]; //定义一个数组为999的大小,每一个元素都是一条链子;
public int size() {//返回一个长度方法
return size;
}
public void put(Object key,Object value) {//一个get方法
//使用hashcode()函数求值,并取数组的长度的余数;
int a = key.hashCode()%arr.length;
//这里定义一个Entry类,用来存两个数;
Entry e = new Entry(key,value);
//定义一个链条
MyLinkedList list = new MyLinkedList();
//判断这个数组的元素是否为空,这里的每个数组元素都是一条链;
if(arr[a]==null) {
// 通过list添加键值
list.add(e);
// 将链条重新赋给arr数组,毕竟存起来的是数组
arr[a] = list ;
// 在这里计算size
size++;
// 以下是arr[a]数组非空的情况下,要判断是否要覆盖
}else {
// 原先中的arr[a]链条赋给list;
list = arr[a];
// 进行遍历list
for(int i=0;i<list.size();i++) {
// 取出list中的值,将其存入Entry类
Entry en = (Entry) list.get(i);
// 进行判断,链子中是否有相同的key,如果有就把最新的值覆盖掉之前的值;
if(en.key.equals(key)) {
en.value=value;//将值进行简单的覆盖即可
break;//覆盖后退出
}
list.add(e);//如果没有相等的值,就直接在后面使用add()函数填入即可;
arr[a] = list;//因为实际存储的还是arr数组,所以要将链条赋值给数组;
}
}
}
//一个get方法
public Object get(Object key) {
// 一样的先求取哈希值
int a = key.hashCode()%arr.length;//求取哈希值
// 进行反判断,arr数组是否为空
if(arr[a]!=null) {
MyLinkedList list =arr[a];
// 进行遍历,查询到已有key值和目前查询key值是否相等;
for(int i=0;i<list.size();i++) {
Entry e = (Entry) list.get(i);
if(e.key.equals(key)) {
return e.value;//如果相等,就将值取出;
}
}
}
return null;//否则回复null
}
public static void main(String[] args) {
MyMap mp = new MyMap();
mp.put("123",45);
mp.put(new Integer(456), "神");
System.out.println(mp.size());
}
}
//定义一个类用来专门存放键值对
class Entry{
public Object value;
public Object key;
public Entry(Object value, Object key) {//一个构造方法;用来存取键值对;
super();
this.value = value;
this.key = key;
}
}
各个类的结合可能有错,但是基本思维应该是没有错的;
3. TreeMap介绍和使用
- TreeMap是典型红黑二叉树的实现;
- TreeMap和HashMap实现了同样的接口Map,但是HashMap的效率要高于TreeMap,一般如果Map需要排序时,就会使用TreeMap;
public class MyTreeMap {
public static void main(String[] args) {
Map<Integer,String> treemap = new TreeMap<Integer, String>();
treemap.put(1,"dxs");//放入元素;
treemap.put(3, "莫须有");
treemap.put(2,"神秘的天");
for(Integer key:treemap.keySet()) {//用foreach直接输出;
System.out.println(key+"-"+treemap.get(key));
}
}
}
最后的结果输出时是按key值的顺序输出的;
自己写的类使用TreeMap进行排序
红黑二叉树就不过多赘述,等我学了再说;
自己写一个简单的类,然后使用TreeMap进行排序;
public class MyTreeMap {
public static void main(String[] args) {
Map<textclass,String> treemap = new TreeMap<textclass, String>();
treemap.put(new textclass(1, 100000), "dxs");
treemap.put(new textclass(3, 500), "神秘的天");
treemap.put(new textclass(2, 6000), "神天");
treemap.put(new textclass(2, 6000), "无意");//仅仅是为了测试是否还是满足map特性,key不重复,结果是满足
for(textclass key:treemap.keySet()) {//通过keySet方法可以得到这个类的Key值:然后赋值给key变量进行遍历;
System.out.println(key+"-"+treemap.get(key));
}
}
}
class textclass implements Comparable<textclass>{
public int id;
public int salary;
public textclass(int id, int salary) {
super();
this.id = id;
this.salary = salary;
}
@Override
public String toString() {//简单重写一个toString方法用于输出完整的key值;否则只会输出对象地址,无法输出准确的key;
return ""+id+"-"+salary;
}
@Override
public int compareTo(textclass o) {
/*一下是该方法的介绍
* Compares this object with the specified object for order. Returns a negative
* integer, zero, or a positive integer as this object is less than, equal to,
* or greater than the specified object.
*
* 意思大概就是说CompareTo主要用于对象的排序,返回一个负数,0,或者正整数,看做是小于,等于和大于,对于那些具体的对象来说;
* 他这里进行比较的是以当前对象,也就是this为主,和他进行比较的对象称之为具体对象,也就是o所代表的对象;
* 如果this对象的属性大于o对象的属性就返回1;小于就返回-1,否则就返回0;
*/
if(this.id<o.id) {
return -1;
}else if(this.id>o.id) {
return 1;
}else if(this.salary<o.salary) {
return -1;
}else if(this.salary>o.salary){
return 1;
}else {
return 0;
}
}
}
下图是程序运行的结果;