欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Core Java Tutorial -,corejavatutorial

来源: javaer 分享于  点击 2741 次 点评:155

Core Java Tutorial -,corejavatutorial


Java HashMap 是 Java 最流行的集合类之一。Java HashMap 是基于哈希表实现的。HashMap 扩展于实现 Map 接口的 AbstractMap 类。

Java HashMap

Java 中有关 HashMap 的一些重要观点有:

Java HashMap Constructors

Java HashMap 提供四个构造器:

Java HashMap Constructors Example

下面的代码片段显示了使用上述所有构造函数的 HashMap 示栗。

Map<String, String> map1 = new HashMap<>();

    Map<String, String> map2 = new HashMap<>(2 ^ 5);

    Map<String, String> map3 = new HashMap<>(32, 0.80f);

    Map<String, String> map4 = new HashMap<>(map1);
}

Java HashMap Methods

让我们来看一下 HashMap 的一些重要方法:

Java 8 引入了很多新的 HashMap 方法。

Java HashMap Example

HashMap 常用方法示栗:

package HashMap;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapExample {
    public static void main(String[] args) {

        //Map<String, String> map = new HashMap<>();

        var map = new HashMap<String, String>(); // Java 10 new feature

        map.put("1", "1"); // put example
        map.put("2", "2");
        map.put("3", "3");
        map.put("4", null); // null value
        map.put(null, "100"); // null key

        String value = map.get("3"); // get example
        System.out.println("Key = 3, Value = " + value);

        value = map.getOrDefault("5", "Default Value");
        System.out.println("Key = 5, Value= " + value);

        boolean keyExists = map.containsKey(null);
        boolean valueExists = map.containsValue("100");

        System.out.println("keyExists = " + keyExists + ", valueExists =" + valueExists);

        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        System.out.println(entrySet);

        System.out.println("map size =" + map.size());

        Map<String, String> map1 = new HashMap<>();
        map1.putAll(map);
        System.out.println("map1 mappings = " + map1);

        String nullKeyValue = map1.remove(null);
        System.out.println("map1 null key value = " + nullKeyValue);
        System.out.println("map1 after removing null key = " + map1);

        Set<String> keySet = map.keySet();
        System.out.println("map keys = " + keySet);

        Collection<String> values = map.values();
        System.out.println("map values = " + values);

        map.clear();
        System.out.println("map is empty=" + map.isEmpty());


    }
}

输出结果:

Key = 3, Value = 3
Key = 5, Value= Default Value
keyExists = true, valueExists =true
[null=100, 1=1, 2=2, 3=3, 4=null]
map size =5
map1 mappings = {null=100, 1=1, 2=2, 3=3, 4=null}
map1 null key value = 100
map1 after removing null key = {1=1, 2=2, 3=3, 4=null}
map keys = [null, 1, 2, 3, 4]
map values = [100, 1, 2, 3, null]
map is empty=true

How HashMap works in java?

Java 中的 HashMap 使用它内部类 Node<K, V> 来存储映射,HashMap 运行在散列算法上,对键的 get 和 put 操作采用 hashCode()equals() 方法。

HashMap 使用单链表存储元素,这些元素被称为仓或桶。当我们调用 put 方法,键的 hasCode 方法被用来确定将用于存储映射的存储桶。

一旦桶确定了,hashCode 方法用来检查是否已经存在相同 hashCode 的键。如果存在,将 equals() 方法将被对键使用。如果 equals() 方法返回 true,就覆盖其值。否则在单链桶中创建新映射。如果没有具有相同 hashCode 的键,则将映射插入到存储桶中。

对于 HashMap get 操作,在此使用 key 的 hashCode 来确定要查找该值的存储区。在确定桶之后,使用 hashCode 和 equals 方法查找遍历条目来查找条目。如果找到匹配,则返回值,否则返回 null。

还涉及更多的事情,栗如哈希算法来获取键的桶,映射的重散列等。但是对于我们,只要记住 HashMap 操作对 Key 有效,并且需要 hashCode 和 equals 方法的良好实现以避免不需要的行为。

建议阅读:hashCode and equals method importance in Java

Java HashMap Load Factor

加载因子用来计算何时重新映射 HashMap 并增加桶大小。桶的默认值或容量是 16,加载因子是 0.75。重散列的阈值时通过容量和加载因子相乘计算的。所以默认阈值是 12。因此,当 HashMap 具有多个于 12 个是映射时,其将被重散列并且桶的数量将被增加到下一幂,即 32。注意,HashMap 容量始终为 2 的幂。

Java HashMap keySet

Java HashMap keySet 方法返回 HashMap 中键的 Set 集合视图。此 Set 集合视图由 HashMap 支持,并且 HashMap 中的任何更改都反映在 Set 中,反之亦然。下面是一个演示 HashMap keySet 示栗的简单程序,如果你希望 keySet 不由 Map 支持,那么该怎么办。

package HashMap;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class HashMapKeySetExample {
    public static void main(String[] args) {

        //Map<String, String> map = new HashMap<>();

        var map = new HashMap<String, String>();

        map.put("1", "1");
        map.put("2", "2");
        map.put("3", "3");

        Set<String> keySet = map.keySet();
        System.out.println(keySet);

        map.put("4", "4");
        System.out.println(keySet); // keySet is backed by Map

        keySet.remove("1");
        System.out.println(map); // map is also modified

        keySet = new HashSet<>(map.keySet()); // copies the key to new Set
        map.put("5", "5");
        System.out.println(keySet); // keySet is not modified
    }

}

输出结果:

[1, 2, 3]
[1, 2, 3, 4]
{2=2, 3=3, 4=4}
[2, 3, 4]

Java HashMap values

Java HashMap values 方法返回一个 Map 中值的 Collection 集合视图。这个集合由 HashMap 支持,所以 HashMap 中的任何值得更改都反映在 Set 中,反之亦然。下面的一个简单示例确认了 HashMap values Collection 的这种行为。

package HashMap;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class HashMapValuesExample {

    public static void main(String[] args) {

        //Map<String, String> map = new HashMap<>();

        var map = new HashMap<String, String>();

        map.put("1", "1");
        map.put("2", "2");
        map.put("3", null);
        map.put("4", null);
        map.put(null, "100");

        Collection<String> values = map.values();
        System.out.println("map values = " + values);

        map.remove(null);
        System.out.println("map values after removing null key = " + values);

        map.put("5", "5");
        System.out.println("map values after put = " + values);

        System.out.println(map);
        values.remove("1"); // changing values collection
        System.out.println(map); // updates in map too

    }
}

输出:

map values = [100, 1, 2, null, null]
map values after removing null key = [1, 2, null, null]
map values after put = [1, 2, null, null, 5]
{1=1, 2=2, 3=null, 4=null, 5=5}
{2=2, 3=null, 4=null, 5=5}

Java HashMap entrySet

Java HashMap entrySet 方法返回映射的 Set 集合视图。这个 entrySet 由 HashMap 支持,所以任何在 Map 中的修改都会反映到 entrySet 中,反之亦然。来看下下面 HashMap entrySet 示栗程序。

package HashMap;

import java.util.*;
import java.util.Map.Entry;

public class HashMapEntrySetExample {

    public static void main(String[] args) {

        //Map<String, String> map = new HashMap<>();

        var map = new HashMap<String, String>();
        map.put("1", "1");
        map.put("2", null);
        map.put(null, "100");

        Set<Entry<String, String>> entrySet = map.entrySet();

        Iterator<Entry<String, String>> iterator = entrySet.iterator();

        Entry<String, String> next = null;

        System.out.println("map before processing = " + map);
        System.out.println("entrySet before processing = " + entrySet);

        while (iterator.hasNext()) {
            next = iterator.next();
            System.out.println("Processing on: " + next.getValue());
            if (next.getKey() == null) {
                iterator.remove();
            }
        }

        System.out.println("map after processing = " + map);
        System.out.println("entrySet after processing = " + entrySet);

        //Entry simpleEntry = new AbstractMap.SimpleEntry<>("1", "1");
        var simpleEntry = new AbstractMap.SimpleEntry<>("1", "1");
        entrySet.remove(simpleEntry);
        System.out.println("map after removing Entry = " + map);
        System.out.println("entrySet after removing Entry = " + entrySet);

    }
}

输出如下:

map before processing = {null=100, 1=1, 2=null}
entrySet before processing = [null=100, 1=1, 2=null]
Processing on: 100
Processing on: 1
Processing on: null
map after processing = {1=1, 2=null}
entrySet after processing = [1=1, 2=null]
map after removing Entry = {2=null}
entrySet after removing Entry = [2=null]

Java HashMap putIfAbsent

Java 8 中引入的 HashMap putIfAbsent 方法简单示栗:

package HashMap;

import java.util.HashMap;
import java.util.Map;

public class HashMapPutIfAbsentExample {

    public static void main(String[] args) {

        //Map<String, String> map = new HashMap<>();

        var map = new HashMap<String, String>();
        map.put("1", "1");
        map.put("2", null);
        map.put(null, "100");

        System.out.println("map before putIfAbsent = " + map);
        String value = map.putIfAbsent("1", "4");
        System.out.println("map after putIfAbsent = " + map);
        System.out.println("putIfAbsent returns: " + value);

        System.out.println("map before putIfAbsent = " + map);
        value = map.putIfAbsent("3", "3");
        System.out.println("map after putIfAbsent = " + map);
        System.out.println("putIfAbsent returns: " + value);
    }
}

输出结果:

map before putIfAbsent = {null=100, 1=1, 2=null}
map after putIfAbsent = {null=100, 1=1, 2=null}
putIfAbsent returns: 1
map before putIfAbsent = {null=100, 1=1, 2=null}
map after putIfAbsent = {null=100, 1=1, 2=null, 3=3}
putIfAbsent returns: null

Java HashMap forEach

Java 8 中引入了 HashMap forEach 方法。这是个非常的方法,用来对 Map 中的每个条目执行给定操作。直到处理完所有条目或操作抛出异常为止。

package HashMap;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class HashMapForEachExample {

    public static void main(String[] args) {
        //Map<String, String> map = new HashMap<>();
        var map = new HashMap<String, String>();

        map.put("1", "1");
        map.put("2", null);
        map.put(null, "100");

        BiConsumer<String, String> action = new MyBiConsumer();
        map.forEach(action);

        //lambda expression example
        System.out.println("\nHashMap forEach lambda example\n");
        map.forEach((k, v) ->
                System.out.println("Key = " + k + ", Value = " + v));
    }
}

class MyBiConsumer implements BiConsumer<String, String> {

    @Override
    public void accept(String t, String u) {
        System.out.println("Key = " + t);
        System.out.println("Processing on value = " + u);
    }

}

输出结果:

Key = null
Processing on value = 100
Key = 1
Processing on value = 1
Key = 2
Processing on value = null

HashMap forEach lambda example

Key = null, Value = 100
Key = 1, Value = 1
Key = 2, Value = null

Java HashMap replaceAll

HashMap replaceAll 方法可用于用调用该条目上的给定函数的结果替换每个条目的值。这个方法在 Java 8 中添加,我们可以使用 lambda 表达式来表示这个方法参数。

package HashMap;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;

public class HashMapReplaceAllExample {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("1", "1");
        map.put("2", "2");
        map.put(null, "100");

        System.out.println("map before replaceAll = " + map);
        BiFunction<String, String, String> function = new MyBiFunction();
        map.replaceAll(function);
        System.out.println("map after replaceAll = " + map);

        // replaceAll using lambda expressions
        map.replaceAll((k, v) -> {
            if (k != null) return k + v;
            else return v;
        });
        System.out.println("map after replaceAll lambda expression = " + map);

    }

}

class MyBiFunction implements BiFunction<String, String, String> {

    @Override
    public String apply(String t, String u) {
        if (t != null)
            return t + u;
        else
            return u;
    }

}

输出:

map before replaceAll = {null=100, 1=1, 2=2}
map after replaceAll = {null=100, 1=11, 2=22}
map after replaceAll lambda expression = {null=100, 1=111, 2=222}

Java HashMap computeIfAbsent

HashMap computeIfAbsent 方法仅在键不存在于 Map 中时才计算该值。计算完值后,如果它不为 null,则将其放入地图中。

package HashMap;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class HashMapComputeIfAbsent {
    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("1", "10");
        map.put("2", "20");
        map.put(null, "100");

        Function<String, String> function = new MyFunction();
        map.computeIfAbsent("3", function); // key not present
        map.computeIfAbsent("2", function); // key already present

        //lambda way
        map.computeIfAbsent("4", v -> v);
        map.computeIfAbsent("5", v -> null); // null value won't get inserted
        System.out.println(map);
    }

}

class MyFunction implements Function<String, String> {

    @Override
    public String apply(String t) {
        return t;
    }

}

输出:

{null=100, 1=10, 2=20, 3=3, 4=4}

Java HashMap computeIfPresent

Java HashMap computeIfPresent 方法在指定的键存在且值不为空时重新计算值。如果该函数返回 null,则映射将被删除。

package HashMap;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;

public class HashMapComputeIfPresentExample {


    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("1", "10");
        map.put("2", "20");
        map.put(null, "100");
        map.put("10", null);

        System.out.println("map before computeIfPresent = " + map);
        BiFunction<String, String, String> function = new MyBiFunction1();
        for (String key : map.keySet()) {
            map.computeIfPresent(key, function);
        }

        System.out.println("map after computeIfPresent = " + map);
        map.computeIfPresent("1", (k, v) -> null); // mapping will be removed
        System.out.println("map after computeIfPresent = " + map);

    }

}

class MyBiFunction1 implements BiFunction<String, String, String> {

    @Override
    public String apply(String t, String u) {
        return t + u;
    }

}

输出:

map before computeIfPresent = {null=100, 1=10, 2=20, 10=null}
map after computeIfPresent = {null=null100, 1=110, 2=220, 10=null}
map after computeIfPresent = {null=null100, 2=220, 10=null}

Java HashMap compute

如果你想基于它的键和值在所有的映射上应用一个函数,那么应该使用计算方法。如果没有映射并且使用此方法,则计算函数的值将为空。

package HashMap;

import java.util.HashMap;
import java.util.Map;

public class HashMapComputeExample {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("1", "1");
        map.put("2", "2");
        map.put(null, "10");
        map.put("10", null);

        System.out.println("map before compute = " + map);
        for (String key : map.keySet()) {
            map.compute(key, (k, v) -> k + v);
        }
        map.compute("5", (k, v) -> k + v); //key not present, v = null
        System.out.println("map after compute = " + map);
    }

}

输出:

map before compute = {null=10, 1=1, 2=2, 10=null}
map after compute = {null=null10, 1=11, 2=22, 5=5null, 10=10null}

Java HashMap merge

如果指定键不存在或者与空关联,则将其与给定的非空值相关联。否则,否则,使用给定的重映射函数的结果替换关联的值,或者如果结果为 null ,则将其删除。

package HashMap;

import java.util.HashMap;
import java.util.Map;

public class HashMapMergeExample {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("1", "1");
        map.put("2", "2");
        map.put(null, "10");
        map.put("10", null);

        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            //merge throws NullPointerException if key or value is null
            if (key != null && value != null)
                map.merge(entry.getKey(), entry.getValue(),
                        (k, v) -> k + v);
        }
        System.out.println(map);

        map.merge("5", "5", (k, v) -> k + v); // key not present
        System.out.println(map);

        map.merge("1", "1", (k, v) -> null); // method return null, so remove
        System.out.println(map);

    }

}

输出:

{null=10, 1=11, 2=22, 10=null}
{null=10, 1=11, 2=22, 5=5, 10=null}
{null=10, 2=22, 5=5, 10=null}

相关文章

    暂无相关文章
相关栏目:

用户点评