Set跟HashMap

Set和HashMap

  发现 Set和HashMap之间还是有很多需要注意的地方:

  HashMap<String,String> map = new HashMap<String,String>();
        map.put("1", "11");
        map.put("2", "22");
        map.put("3", "33");

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

  1. map的keySet()方法只返回一个set实例,所以当从key1中删除一个对象时候,其他也将会受到影响。map里面的元素收到影响;

  2. 针对于 set不能进行 add操作 ,否则会报“java.lang.UnsupportedOperationException” 。原因 如下 :

  public Set<K> keySet()返回此映射中所包含的键的 set 视图。该集合受映射的支持,所以映射的变化也反映在该集合中,反之亦然。该集合支持元素的移除,通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作,从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。

  3.

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

  for (String key : set) {

  map.remove(key);

  }

  此代码 报这个异常: Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at com.nan.an.jing.TestSet.main(TestSet.java:23)

  原因 为 : 因为删除了一个Entry之后,因为ketSet不正确,在for循环时出的问题。

  改正的方法为:

  String[] keySet = map.keySet().toArray(new String[0]);

  for (String key : keySet) {

  map.remove(key);

  }

  或者

  Object[] keySet = map.keySet().toArray();
for (Object key : keySet) {
map.remove((String)key);
}

  附注 : 代码实例

  1. package com.nan.an.jing; 
  2. import java.util.ArrayList; 
  3. import java.util.HashMap; 
  4. import java.util.Iterator; 
  5. import java.util.List; 
  6. import java.util.Map; 
  7. import java.util.Map.Entry; 
  8. import java.util.Set; 
  9. public class TestSet { 
  10.   public static void main(String[] args) { 
  11.    HashMap<String,String> map = new HashMap<String,String>(); 
  12.    map.put("1", "aa"); 
  13.    map.put("2", "bb"); 
  14.    map.put("3", "aa"); 
  15.    map.remove("1"); 
  16.    //必须转换为array,或者 String[] keySet = map.keySet().toArray(new String[0]); 
  17.    Object[] keySet = map.keySet().toArray(); 
  18.    for (Object key : keySet) { 
  19.     map.remove((String)key); 
  20.    }  
  21.    System.out.println(map); 
  22.    // set仅仅一个实例,set删除,map也跟随删除 
  23.    Set<String> set = map.keySet(); 
  24.    set.remove("1"); 
  25.    System.out.println(set); 
  26.    System.out.println(map); 
  27.    // 采用 iterator方法删除 map 
  28.    for(Iterator<String> iterator = set.iterator();iterator.hasNext();) 
  29.    { 
  30.      iterator.next(); 
  31.      iterator.remove(); 
  32.    } 
  33.    System.out.println(map); 
  34.    // 采用iterator方法获取map信息 
  35.    Set<Entry<String, String$amp;>amp;$gt; set0 = map.entrySet(); 
  36.    for(Iterator<Map.Entry<String, String$amp;>amp;$gt; iterator = set0.iterator();iterator.hasNext();){ 
  37.      Map.Entry<String, String> mm = iterator.next(); 
  38.      String key1 = mm.getKey(); 
  39.      String value = mm.getValue(); 
  40.    } 
  41.    System.out.println(set0); 
  42.    // 采用list增加元素 
  43.    HashMap<String,String> map1 = new HashMap<String,String>(); 
  44.    map1.put("1", "aa"); 
  45.    map1.put("2", "bb"); 
  46.    Set<String> set1 = map1.keySet(); 
  47.    List<String> ll = new ArrayList<String>();  
  48.    for(String ss : set1){ 
  49.      ll.add(ss); 
  50.    }  
  51.    ll.add("cc"); 
  52.    System.out.println(ll); 
  53.    System.out.println(map1); 
  54. } 
  55. }

 

 

如何遍历???

或许你已经知道,HashSet其实是一个披着Set方法外衣的HashMap;同样,TreeSet其实也是一个披着Set方法外衣的TreeMap。Map并不支持直接用迭代器进行遍历,因此下面的这段代码编译无法通过:

1

2

3

Map<String, Double> salaries = new HashMap<>();

for(double salary : salaries) { // does not compile

}

我们可以通过遍历Map中的key集合、value集合和entry集合来实现Map的遍历。由于Map中的value是可以重复出现的,因此values()方法返回的是一个Collection类型的集合。而Map中的key是不允许重复的,因此keySet()方法和entrySet()返回的都是Set类型的集合。

因此,我们可以采用下面的方法来遍历Map:

1

2

3

Map<String, Double> salaries = new HashMap<>();

for (double salary : salaries.values()) {

}

或者可以通过遍历key来遍历Map:

1

2

3

Map<String, Double> salaries = new HashMap<>();

for (String name : salaries.keySet()) {

}

当然,还可以通过遍历entry来遍历Map:

1

2

3

4

5

Map<String, Double> salaries = new HashMap<>();

for (Map.Entry<String, Double> entry : salaries.entrySet()) {

  String name = entry.getKey();

  double salary = entry.getValue();

}

我经常看到程序员这样遍历Map:先获取keySet,然后对keys进行遍历,并通过get()方法找到对应的value。

1

2

3

4

Map<String, Double> salaries = new HashMap<>();

for (String name : salaries.keySet()) { // less efficient way to

    double salary = salaries.get(name);   // iterate over entries

}

从直观上看,采用遍历entry的方式遍历Map会更加高效一些,这种遍历方式的时间复杂度是O(n)。然而,如果HashMap中的元素分布均匀,调用get()方法查找元素的时间复杂度将是O(1),那么这两种方法遍历HashMap的时间复杂度是一样的,都是O(n)。这两种遍历方式虽然有所不同,但时间复杂度都是线性的。但这个结论并不适用于其它类型的Map,特别是TreeMap。TreeMap的平均查找效率是O(log n),因此通过keySet遍历TreeMap的时间复杂度是O(n x log n)。

转载于:https://my.oschina.net/u/2365905/blog/849395

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值