Java学习-Map接口

Map接口概述

Map:双列集合类的根接口,用于存储具有键(Key)、值(Value)映射关系的元素,每个元素都包含一对键值,在使用Map集合时可以通过指定的Key找到对应的Value,例如根据一个学生的学号就可以找到对应的学生。Map接口的主要实现类有HashMap和TreeMap。

将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。其实Map集合中存储的就是键值对。map集合中必须保证键的唯一性。

Map接口和Collection接口的不同

  • Map是双列的,Collection是单列的
  • Map的键唯一,Collection的子体系Set是唯一的
  • Map集合的数据结构值针对键有效,跟值无关
  • Collection集合的数据结构是针对元素有效

Map常用的子类:

  • Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值。
  • Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
  • HashMap:内部结构式哈希表,不是同步的。允许null作为键,null作为值。
  • TreeMap:内部结构式二叉树,不是同步的。可以对Map结合中的键进行排序。
  • HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。

Map接口常用方法

方法声明功能描述
put(K key, V value)有添加和替换功能
putAll(Map m)添加一个Map的元素
clear()清空集合
remove(Object key)根据键删除一个元素
containsKey()判断集合是否包含指定的键
containsValue()判断集合是否包含指定的值
isEmpty()判断集合是否为空
get(Object key)根据键获取值
keySet()获取所有的键
values()获取所有的值
entrySet()获取所有的Entry
size()获取集合元素的个数

 

HashMap

键是哈希表结构,可以保证键的唯一性

LinkedHashMap

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。

TreeMap

键是红黑树结构,可以保证键的排序和唯一性,自然排序,比较器排序。

package com.lcy.javaMap;
 
import java.util.TreeMap;
//键不可以重复,值可以重复    键可以排序,有排序要注意键的类型 <String>要实现Comparable接口
public class TreeMapDemo {
    public static void main(String[] args) {
        TreeMap<String,String>a=new TreeMap();
        a.put("a", "aa");
        a.put("g", "gg");
        a.put("b", "bb");
        a.put("c", "cc");
        a.put("e", "ee");
        a.put("d", "tt");
 
        System.out.println(a);
     // 输出结果:{a=aa, b=bb, c=cc, d=tt, e=ee, g=gg}
 
    }
}

Hashtable

package com.lcy.javaMap;
 
import java.util.Hashtable;
//键不能重复,值可以重复  无序 是线程安全的
public class HashtableDemo {
    public static void main(String[] args) {
        Hashtable <String,String>s=new Hashtable();
        s.put("a", "aa");
        s.put("v", "vv");
        s.put("l", "ll");
        //s.put(null, "tt");//键和值都不能为null  NullPointerException空指针异常
        System.out.println(s);
       // 输出结果:{l=ll, a=aa, v=vv}
 
    }
}

Map集合遍历

方式1:根据键找值。获取所有键的集合,遍历键的集合,获取到每一个键,根据键找值。

package cn.itcast;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
 * Map集合的遍历。
 * Map -- 夫妻对
 * 思路:
 *         A:把所有的丈夫给集中起来。
 *         B:遍历丈夫的集合,获取得到每一个丈夫。
 *         C:让丈夫去找自己的妻子。
 * 
 * 转换:
 *         A:获取所有的键
 *         B:遍历键的集合,获取得到每一个键
 *         C:根据键去找值
 */
public class MapDemo {
    public static void main(String[] args) {
        // 创建集合对象
        Map<String, String> map = new HashMap<String, String>();
        // 创建元素并添加到集合
        map.put("杨过", "小龙女");
        map.put("郭靖", "黄蓉");
        map.put("杨康", "穆念慈");
        map.put("陈玄风", "梅超风");
        // 遍历
        // 获取所有的键
        Set<String> set = map.keySet();
        // 遍历键的集合,获取得到每一个键
        for (String key : set) {
            // 根据键去找值
            String value = map.get(key);
            System.out.println(key + "---" + value);
        }
    }
}

方式2:根据键值对对象找键和值。

  • 获取所有键值对对象的集合
  • 遍历键值对对象的集合,获取到每一个键值对对象
  • 根据键值对对象找键和值
package cn.itcast;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
 * Map集合的遍历。
 * Map -- 夫妻对
 * 
 * 思路:
 *         A:获取所有结婚证的集合
 *         B:遍历结婚证的集合,得到每一个结婚证
 *         C:根据结婚证获取丈夫和妻子
 * 
 * 转换:
 *         A:获取所有键值对对象的集合
 *         B:遍历键值对对象的集合,得到每一个键值对对象
 *         C:根据键值对对象获取键和值
 * 
 * 这里面最麻烦的就是键值对对象如何表示呢?
 * 看看我们开始的一个方法:
 *         Set<Map.Entry<K,V>> entrySet():返回的是键值对对象的集合
 */
public class MapDemo {
    public static void main(String[] args) {
        // 创建集合对象
        Map<String, String> map = new HashMap<String, String>();
        // 创建元素并添加到集合
        map.put("杨过", "小龙女");
        map.put("郭靖", "黄蓉");
        map.put("杨康", "穆念慈");
        map.put("陈玄风", "梅超风");
        // 获取所有键值对对象的集合
        Set<Map.Entry<String, String>> set = map.entrySet();
        // 遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : set) {
            // 根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "---" + value);
        }
    }
}

Map集合的应用及扩展

package cn.itcast;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
/*
 * 需求 :"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
 * 
 * 分析:
 *         A:定义一个字符串(可以改进为键盘录入)
 *         B:定义一个TreeMap集合
 *             键:Character
 *             值:Integer
 *         C:把字符串转换为字符数组
 *         D:遍历字符数组,得到每一个字符
 *         E:拿刚才得到的字符作为键到集合中去找值,看返回值
 *             是null:说明该键不存在,就把该字符作为键,1作为值存储
 *             不是null:说明该键存在,就把值加1,然后重写存储该键和值
 *         F:定义字符串缓冲区变量
 *         G:遍历集合,得到键和值,进行按照要求拼接
 *         H:把字符串缓冲区转换为字符串输出
 * 
 * 录入:linqingxia
 * 结果:result:a(1)g(1)i(3)l(1)n(2)q(1)x(1)
 */
public class TreeMapDemo {
    public static void main(String[] args) {
        // 定义一个字符串(可以改进为键盘录入)
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String line = sc.nextLine();
        // 定义一个TreeMap集合
        TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
        // 把字符串转换为字符数组
        char[] chs = line.toCharArray();
        // 遍历字符数组,得到每一个字符
        for (char ch : chs) {
            // 拿刚才得到的字符作为键到集合中去找值,看返回值
            Integer i = tm.get(ch);
            // 是null:说明该键不存在,就把该字符作为键,1作为值存储
            if (i == null) {
                tm.put(ch, 1);
            } else {
                // 不是null:说明该键存在,就把值加1,然后重写存储该键和值
                i++;
                tm.put(ch, i);
            }
        }
        // 定义字符串缓冲区变量
        StringBuilder sb = new StringBuilder();
        // 遍历集合,得到键和值,进行按照要求拼接
        Set<Character> set = tm.keySet();
        for (Character key : set) {
            Integer value = tm.get(key);
            sb.append(key).append("(").append(value).append(")");
        }
        // 把字符串缓冲区转换为字符串输出
        String result = sb.toString();
        System.out.println("result:" + result);
    }
}

示例2:在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。

package cn.itcast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
class Student {
    private String name;
    private int age;
    public Student() {
        super();
    }
    public Student(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;
    }
}
/*
 *         bj    北京校区
 *             jc    基础班
 *                     林青霞        27
 *                     风清扬        30
 *             jy    就业班    
 *                     赵雅芝        28
 *                     武鑫        29
 *         sh    上海校区
 *             jc    基础班
 *                     郭美美        20
 *                     犀利哥        22
 *             jy    就业班    
 *                     罗玉凤        21
 *                     马征        23
 *         gz    广州校区
 *             jc    基础班
 *                     王力宏        30
 *                     李静磊        32
 *             jy    就业班    
 *                     郎朗        31
 *                     柳岩        33
 *         xa    西安校区
 *             jc    基础班
 *                     范冰冰        27
 *                     刘意        30
 *             jy    就业班    
 *                     李冰冰        28
 *                     张志豪        29
 */
public class HashMapDemo {
    public static void main(String[] args) {
        // 创建大集合
        HashMap<String, HashMap<String, ArrayList<Student>>> czbkMap = new HashMap<String, HashMap<String, ArrayList<Student>>>();
        // 北京校区数据
        HashMap<String, ArrayList<Student>> bjCzbkMap = new HashMap<String, ArrayList<Student>>();
        ArrayList<Student> array1 = new ArrayList<Student>();
        Student s1 = new Student("林青霞", 27);
        Student s2 = new Student("风清扬", 30);
        array1.add(s1);
        array1.add(s2);
        ArrayList<Student> array2 = new ArrayList<Student>();
        Student s3 = new Student("赵雅芝", 28);
        Student s4 = new Student("武鑫", 29);
        array2.add(s3);
        array2.add(s4);
        bjCzbkMap.put("基础班", array1);
        bjCzbkMap.put("就业班", array2);
        czbkMap.put("北京校区", bjCzbkMap);
        // 西安校区数据
        HashMap<String, ArrayList<Student>> xaCzbkMap = new HashMap<String, ArrayList<Student>>();
        ArrayList<Student> array3 = new ArrayList<Student>();
        Student s5 = new Student("范冰冰", 27);
        Student s6 = new Student("刘意", 30);
        array3.add(s5);
        array3.add(s6);
        ArrayList<Student> array4 = new ArrayList<Student>();
        Student s7 = new Student("李冰冰", 28);
        Student s8 = new Student("张志豪", 29);
        array4.add(s7);
        array4.add(s8);
        xaCzbkMap.put("基础班", array3);
        xaCzbkMap.put("就业班", array4);
        czbkMap.put("西安校区", xaCzbkMap);
        // 遍历集合
        Set<String> czbkMapSet = czbkMap.keySet();
        for (String czbkMapKey : czbkMapSet) {
            System.out.println(czbkMapKey);
            HashMap<String, ArrayList<Student>> czbkMapValue = czbkMap
                    .get(czbkMapKey);
            Set<String> czbkMapValueSet = czbkMapValue.keySet();
            for (String czbkMapValueKey : czbkMapValueSet) {
                System.out.println("\t" + czbkMapValueKey);
                ArrayList<Student> czbkMapValueValue = czbkMapValue
                        .get(czbkMapValueKey);
                for (Student s : czbkMapValueValue) {
                    System.out.println("\t\t" + s.getName() + "---"
                            + s.getAge());
                }
            }
        }
    }
}

补充知识

1.HashSet中为什么不能存储重复元素,如何判断元素是否重复
在add()的底层方法中,每添加一个元素,就会判断集合中是否包含了此元素

在底层使用hashCode()和equals()方法来判断内容是否重复

hashCode()是Object类中的方法

public native int hashCode();native修饰的方法没有方法体,称为本地方法,java没有实现,是调用操作系统的方法

Object类中的hashCode()方法是用来获取对象在内存中的地址

其他类中重写hashCode()方法是用来根据对象内容计算出来的哈希值(a-->97)

Object类中的equals()是比较两个对象的地址

其他类约定equals()用来比较对象的内容是否相等

equals()效率太低,要把每个位置上的字符进行对比

在判断两个元素是否相同时,先用hashCode()方法比较两个元素内容的哈希值.

但是此种做法并不安全,2个不同的内容也可能算出同样的哈希值(比如说中文里的"通话"和"重地")

这两个元素虽然内容不同,但是算出来的哈希值相同,此时就又调用了equals()方法,来比较它们的内容是否相同。

2.HashMap的底层结构

3.HashMap中添加元素的过程
根据添加的元素计算出一个hash值(a-->97),再进行一次计算,计算出元素在数组中的位置(例如97%16=1;那么就放在第一个位置)然后继续有元素存储进来,如果存在了相同的位置,将新的元素存入一个之前元素的下一位,当链表长度达到8(并且数组长度大于64时)会把链表转化为红黑树

哈希数组长度默认是16

负载因子是0.75(16*0.75=12,有3/4的数组被存储的时候,哈希数组就会扩容)

哈希数组如果扩容每次扩容到原来的2倍

当链表长度到达8,并且哈希数组长度大于64,链表会转为红黑树

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
package com.MangoMap; //import android.app.Activity; import com.google.android.maps.MapActivity; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.view.View; import android.widget.ListView; import android.widget.SimpleAdapter; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; //MapView Com import com.google.android.maps.MapView; import com.google.android.maps.MapController; import com.google.android.maps.GeoPoint; //import com.google.android.maps. public class MangoMap extends MapActivity { /** Called when the activity is first created. */ private MapView mpv; private MapController mpc; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //地图 mpv = (MapView) findViewById(R.id.map); mpv.setTraffic(true); mpv.setClickable(true); mpv.setScrollContainer(true); mpc = mpv.getController(); GeoPoint gp = new GeoPoint((int) (23.05320 * 1000000), (int) (113.155550 * 1000000)); //地理坐标 mpc.animateTo(gp); mpc.setZoom(15); //mpc. // } @Override protected boolean isRouteDisplayed() { return false; } } //----------------- <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> --> <com.google.android.maps.MapView android:id="@+id/map" android:layout_width="fill_parent" android:layout_height="fill_parent" android:enabled="true" android:clickable="true" android:apiKey="YOUR API key" /> <Button android:text="@+id/Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout> //--------------------- <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.MangoMap" android:versionCode="1" android:versionName="1.0"> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="com.google.android.maps" /> <activity android:name=".MangoMap" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> </manifest>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da白兔萘糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值