Java核心技术-集合-映射

一 基本映射操作

1 映射用来存放键/值对

2 映射提供了两种通用的实现:HashMapTreeMap,两个类都实现了Map接口

    散列映射对键进行散列;树映射用键的整体顺序对元素进行排序,并将其组织成搜索树

    散列或比较函数只能作用于键,与键关联的值不能进行散列或比较

3应该如何选择散列或者树?与集合一样,散列的速度稍快一些,如果不需要按照排列顺序访问键,就最好选择散列。

     

   Map<String,Employee> staff = new HashMap<>();//HashMap implements Map

        Employee harry = new Employee("tiffany");

        staff.put("3245", harry);

在这里键是一个字符串,对应的值是Employee对象。要想检索一个对象,必须使用一个键。

        String id = "3245";

        e = staff.get(id)

扫描二维码关注公众号,回复: 2538999 查看本文章

 如果在映射中没有与给定键对应的信息,get就返回null

5 键必须是唯一的,不能对同一个键存放两个值。如果对同一个键两次调用put方法,第二个值就会取代第一个值。

6 用forEach迭代处理映射的键和值,例

staff.forEach((k,v)->

        System.out.println("key"+k+",value="+v));

Map类常用方法:

V get(Object key):获取与键对应的值或对象

default V getOrDefault(Object key,V defaultValue):获取与键关联的值或对象

V put(K key,V value):将键与对应得到值关系插入到映射中

。。。

二 更新映射项

1 如何处理更新映射项时键第一次出现的情况:

  •     counts.put(word,counts.getOrDefault(word,0)+1);
    
        counts,putIfAbsent(word,0);
    
        counts.put(word,counts.get(word)+1);
    
        counts.merge(word,1,Integer::sum);//将把word与1关联,否则使用Integer::sum函数组合原值和1

三 映射视图

1 三种视图:键集,值集合,键/值对集

  • Set<K> keySet()
    
    Collection<V> values()
    
    Set<Map.Entry<K,V>> entrySet()

这三种方法会分别返回这3个视图,其中keySet既不是HashSet也不是TreeSet,而是实现了Set接口的另外某个类的对象。Set接口扩展了Collection接口,因此可以像使用集合一样使用keySet

例1:

Set<String> keys = map.keySet();

for(String key:keys){

//可以枚举一个映射的所有键

}

例2:同时查看键和值:

for(Map.Entry<String,Employee> entry:staff.entry.entrySet()){

String k = entry.getKey();

Employee v = entry.getValue();

}

四 弱散列映射

1 垃圾回收器跟踪活动的对象,只要映射对象是活动的,其中的所有桶也是活动的,它们不能被回收。所以需要由程序负责从长期存活的映射表中删除那些无用的值,或者使用WeakHashMap类

2 WeakHashMap使用弱引用来保存键,WeakHashMap对象将引用保存到另外一个对象(散列键)中

3 通常,如果垃圾回收器发现某个特定的对象已经没有他人引用了,就将其回收。但对于只能由WeakReference引用的对象,垃圾回收器仍然要回收它,但是要将引用这个对象的弱引用放入队列中。WeakHashMap将周期性地检查队列,以便找出新添加的弱引用,然后将其删除

五 链接散列集和映射

1 为了避免在散列表中的项从表面上看起来是随机排列的,可以使用LinkedHashSet和LinkedHashMap类来记住插入元素项的顺序。

例:        

Map<String,Employee> staff = new LinkedHashMap<>();

        staff.put("1234", new Employee("tiffany"));

        staff.put("2345", new Employee("sarah"));

        staff.put("1345", new Employee("jeff"));

        staff.put("3345", new Employee("jelly"));

        Set<String> keys = staff.keySet();

        for (String key : keys) {

            System.out.println(key);

        }

        for (Employee e : staff.values()) {

            System.out.println(e.getName());

        }

2 链接散列映射将用访问顺序,而不是插入顺序,对映射条目进行迭代。

3 可以使用LinkedHashMap来实现访问顺序这一目的:将访问频率高的元素放到内存中,而访问频率低的元素从数据库中读取

可以构造一个LinkedHashMap的子类,然后覆盖下面的方法

protected boolean removeEldestEntry(Map.Entry<K,V> eldest)

六 枚举集与映射

1.EnumSet是一个枚举类型元素集的高效实现。

2.EnumMap是一个键类型为枚举类型的映射。

七 标识散列映射(IdentityHashMap类)

在这个类中,键的散列值不是用hashCode 函数实现计算的,而是用System.identityHashCode方法计算的

在进行对象的比较时,使用的是== ,而不是equals,故比较的是对象

补充:==和equals的区别:

==比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作

equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。

例题:

public class test1 {

   public static void main(String[] args) {

     String a = new String("ab"); // a 为一个引用 
     String b = new String("ab"); // b为另一个引用,对象的内容一样 
     String aa = "ab"; // 放在常量池中

    String bb = "ab"; // 从常量池中查找 

  if     (aa == bb) // true 

     System.out.println("aa==bb");

  if (a == b) // false,非同一对象

     System.out.println("a==b");

     if (a.equals(b)) // true

     System.out.println("aEQb");

     if (42 == 42.0) { // true

     System.out.println("true");

     }

     }

    }

猜你喜欢

转载自blog.csdn.net/wo8vqj68/article/details/81168039