当前位置:   article > 正文

Java/Python/Go不同开发语言基础数据结构和相关操作总结-Map篇

Java/Python/Go不同开发语言基础数据结构和相关操作总结-Map篇

由于最近频繁在java、python、go三种开发语言中不断切换,有时候针对基础的数据结构和日常操作搞混了,因此本文进行相关梳理。文中涉及的相关数据结构和日常操作并不复杂,权当增强记忆和理解。


1. Java

Java 自带了各种 Map 类。这些 Map 类可归为三种类型:

  • 通用Map,用于在应用程序中管理映射,通常在 java.util 程序包中实现
    HashMap、Hashtable、Properties、LinkedHashMap、IdentityHashMap、TreeMap、WeakHashMap、ConcurrentHashMap

  • 专用Map,通常我们不必亲自创建此类Map,而是通过某些其他类对其进行访问
    java.util.jar.Attributes、javax.print.attribute.standard.PrinterStateReasons、java.security.Provider、java.awt.RenderingHints、javax.swing.UIDefaults

  • 一个用于帮助我们实现自己的Map类的抽象类
    AbstractMap

类型说明线程安全
HashMap最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度; HashMap最多只允许一条记录的键为Null(多条会覆盖); 允许多条记录的值为 Null线程不安全
TreeMap能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null线程不安全
HashTable与 HashMap类似,不同的是:key和value的值均不允许为null; 它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。线程安全
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空线程不安全

其中HashMap是最常用的,其他类型的Map根据使用,本文重点介绍HashMap

1.1 基础操作

1.1.1 数据结构和定义方式

# 定义空
Map<String, String> map = new HashMap<>();

# 初始化
  Map<String, String> map = new HashMap<String, String>() {{
      put("a", "b");
      put("b", "b");
  }};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

1.1.2 增加

map.put(K key, V value);
map.put("key1", "value1");
  • 1
  • 2

1.1.3 修改

map.put(K key, V value);
map.put("key", "value");
  • 1
  • 2

1.1.4 查询

# 获取key的值
map.get(Object key);
map.get("key")
  • 1
  • 2
  • 3

1.1.5 删除

map.remove(Object key);
map.remove("key");
  • 1
  • 2

1.1.6 获取总长度

# 获取总长度
int length = map.size();
  • 1
  • 2

1.1.7 按key排序

HashMap本身本身无序,如果需要排序,可以单独整理出key作为列表,然后形成排序,通过有序的key获取对应的value。

List<Map.Entry<String, String>> list = new ArrayList<>(map.entrySet());
list.sort(new Comparator<Map.Entry<String, String>>() {
    @Override
    public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
        return o1.getKey().compareTo(o2.getKey());
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

1.1.8 按value排序

List<Map.Entry<String, String>> list = new ArrayList<>(map.entrySet());
list.sort(new Comparator<Map.Entry<String, String>>() {
    @Override
    public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
        return o1.getValue().compareTo(o2.getValue());
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

1.1.9 遍历

# 整体遍历
for (Map.Entry<String, String> mapping: map.entrySet()) {
    System.out.println(mapping.getKey() + ":" + mapping.getValue());
}
  • 1
  • 2
  • 3
  • 4

1.2 常用其他方法

1.2.1 几种数据结构的对比

在这里插入图片描述

1.2.1 数据拷贝

浅拷贝:只拷贝源对象的地址,所以新对象与老对象共用一个地址,当该地址变化时,两个对象也会随之改变
深拷贝:拷贝对象的所有值,即使源对象发生任何改变,拷贝的值也不会变化。
日常使用比较多是深拷贝,因此需要注意

1.2.1.1 赋值实现浅拷贝
// Map只能实现浅拷贝,paramMap中的内容发生变化,paramMap2中的内容亦同步发生变化
Map<String, String> src = new HashMap<String, String>(){{
	put("name", "Marydon");
}};
paramMap.put("name", "Marydon");
Map<String, String> dst = new HashMap<String, String>();
dst = src;
paramMap.remove("name");
System.out.println(paramMap2);//{}
// 实现浅拷贝方式二:使用Map.putAll()
paramMap2.putAll(paramMap);
paramMap.remove("name");
System.out.println(paramMap2);//{}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
1.2.1.1 Map.putAll()实现浅拷贝

使用Map.putAll()只能实现浅拷贝,修改任意一个都会影响另一个

Map<String, String> src = new HashMap<String, String>(){{
	put("name", "Marydon");
}};
paramMap.put("name", "Marydon");
Map<String, String> dst = new HashMap<String, String>();
dst.putAll(src);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
1.2.1.1 HashMap.putAll()实深拷贝

HashMap.putAll()可以实现深拷贝

 // HashMap可以实现真正意义上深拷贝,注意不是Map
HashMap<String, String> src = new HashMap<String, String>(){{
    put("a", "b");
}};
 HashMap<String, String> dst = new HashMap<String, String>();
 // 实现深拷贝:使用HashMap.putAll()
 dst.putAll(paramMap);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2. Go

go没有定义复杂的数据结构,只有map一种类型,并且不设置容量,能够自动扩容。

2.1基础操作

2.1.1 数据结构和定义方式

# 定义空数据
m := make(map[string]int)
m := map[string]int{}

# 创建一个初始容量为 10 的 Map
m := make(map[string]int, 10)

# 初始化
m1 := map[string]int{
	"张三": 3,
	"李四": 4,
	"王五": 5,
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.1.2 增加

# 指定index后添加元素
m["key"]="value"
  • 1
  • 2

2.1.3 修改

# 指定index后添加元素
m["key"]="value"
  • 1
  • 2

2.1.4 查询

# 指定key后添加元素
var value = m["key"]
  • 1
  • 2

2.1.5 删除

# 指定key后删除元素
delete(m, "key")
  • 1
  • 2

2.1.6 获取总长度

# 获取list的总长度
var length = len(list)
  • 1
  • 2

2.1.7 按key排序

没有提供原生的方法,需要自己实现,将key生成切片,完成切片排序。可以参考Java/Python/Go不同开发语言基础数据结构和相关操作总结-数组篇

// 按照key排序
var keys []int
for k := range m {
    keys = append(keys, k)
}
sort.Ints(keys)

for _, k := range keys {
    fmt.Println("Key:", k, "Value:", m[k])
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.1.8 按value排序

没有提供原生的方法,需要自己实现,将value生成切片,完成切片排序。可以参考Java/Python/Go不同开发语言基础数据结构和相关操作总结-数组篇

 mapInfo := map[string]int32{
     "roy":18,
     "kitty":16,
     "hugo":21,
     "tina":35,
     "jason":23,
 }

 type peroson struct {
     Name string
     Age int32
 }

 // 生成切片
 var lstPerson []peroson
 for k, v := range mapInfo {
     lstPerson = append(lstPerson, peroson {k, v})
 }

 // 切片排序
 sort.Slice(lstPerson, func(i, j int) bool {
     return lstPerson[i].Age < lstPerson[j].Age  // 升序
 })
 fmt.Println(lstPerson)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

2.1.9 遍历

for key, value := range m {
	fmt.Printf("key=%s, value=%d\n", key, value)
}
  • 1
  • 2
  • 3

2.1.10 数据拷贝

2.1.10.1 赋值实现浅拷贝
src := map[string]int{"a": 1}
dst := src
  • 1
  • 2
2.1.10.2 赋值实现深拷贝

没有原生的深拷贝方法,需要循环赋值

src := map[string]int{"a": 1}
dst := map[string]int{}
for k,v := range src {
	dst[k] = v
}
  • 1
  • 2
  • 3
  • 4
  • 5

3. Python

3.1 列表

声明不固定长度的列表,因此能够提供更加丰富的api和操作方法,也是最常用的数据结构。

3.1.1 数据结构和定义方式

# 定义空数据
m = { }

# 初始化
m = {"key1" : "value1", "key2" : "value2" }
  • 1
  • 2
  • 3
  • 4
  • 5

3.1.2 增加

# 指定key
m["key"]="value"
m.add({"key": "value"})
  • 1
  • 2
  • 3

3.1.3 修改

# 指定key
m["key"]="value"
m.update({"key": "value"})
  • 1
  • 2
  • 3

3.1.4 查询

# 指定key
m.get("key")

  • 1
  • 2
  • 3

3.1.5 删除

# 指定key
del m["key"]
  • 1
  • 2

3.1.6 获取总长度

len(m)
  • 1

3.1.7 按key排序

# 按key排序
m1 = sorted(m)
  • 1
  • 2

3.1.8 按value排序

# 按value排序
m1 = sorted(m.items(), key = lambda kv:(kv[1], kv[0]))
  • 1
  • 2

3.1.9 遍历

for key, value in m.items():
    print(key, value)
  • 1
  • 2

3.1.10 数据拷贝

3.1.10.1 赋值实现浅拷贝
src := map[string]int{"a": 1}
dst := src
  • 1
  • 2
3.1.10.2 赋值实现深拷贝
src = {"Name": "HaiCoder", "Age": 100, "Score": 99.5}
dst = src.copy()
  • 1
  • 2
3.1.10.2 copy.copy()实现浅拷贝
import copy
src:= map[string]int{"a": 1}
dst = copy.copy(src)
  • 1
  • 2
  • 3
2.3.4 copy.deepcopy()实现深拷贝
import copy
src:= map[string]int{"a": 1}
dst = copy.deepcopy(src)
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/64766
推荐阅读
相关标签
  

闽ICP备14008679号