Java 中 Map 的5种遍历方式
同系列文章
java 中 List 的5种遍历方式
Java 中 Set 的4中遍历方式
Java 中 Map 的5种遍历方式
主测试方法
@Test
public void test1(){
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int n = 1000_0000;
for (int i = 1; i <= n; i++) {
map.put(i, i);
}
System.out.println("======== 1 entrySet 最常用 ==========");
entrySetTest(map);
System.out.println("======== 2 keySet Or Values 取keys或values 时,效率最高 ==========");
keySetOrValuesTest(map);
//System.out.println("======== keySetForValueTest ==========");
keySetForValueTest(map);
System.out.println("======== 3 iterator Type ==========");
iteratorTypeTest(map);
System.out.println("======== 4 forEach java 8 效率最低 ==========");
forEachTest(map);
System.out.println("======== 5 stream ForEach java 8 流式 ==========");
streamForEachTest(map);
}
1000万数据测试结果
======== 1 entrySet 最常用 ==========
map.entrySet() time= 65
======== 2 keySet Or Values 取keys或values 时,效率最高 ==========
map.keySet() time= 71
map.keySet().iterator() time= 63
map.values() time= 74
map.values().iterator() time= 64
map.keySet() -> map.get(key) time= 107
======== 3 iterator Type ==========
map.entrySet().iterator() time= 85
======== 4 forEach java 8 效率最低 ==========
map.forEach time= 103
======== 5 stream ForEach java 8 流式 ==========
map.entrySet().stream().forEach time= 62
1、最常用的方法,map.entrySet() 加增强for
/**
* 1
* entrySet 这是最常用的方式,在键值都需要的时候
* @param map
*/
public void entrySetTest(Map<Integer, Integer> map){
long before = System.currentTimeMillis();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
entry.getKey();
entry.getValue();
// System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
long after = System.currentTimeMillis();
System.out.println("map.entrySet() time=\t" + (after - before));
}
2、通过keySet() 或 values()获取
/**
* 2(1)keySet values
* 如果只需要键或者值,这个比键值对的要快
* @param map
*/
public void keySetOrValuesTest(Map<Integer, Integer> map){
long before = System.currentTimeMillis();
// 遍历map中的键
for (Integer key : map.keySet()) {
//System.out.println("Key = " + key);
}
long after = System.currentTimeMillis();
System.out.println("map.keySet() time=\t" + (after - before));
before = System.currentTimeMillis();
// 遍历map中的键
Iterator<Integer> iteratorKeySet = map.keySet().iterator();
while (iteratorKeySet.hasNext()) {
iteratorKeySet.next();
//System.out.println("key = " + iteratorKeySet.next());
}
after = System.currentTimeMillis();
System.out.println("map.keySet().iterator() time=\t" + (after - before));
before = System.currentTimeMillis();
// 遍历map中的值
for (Integer value : map.values()) {
//System.out.println("Value = " + value);
}
after = System.currentTimeMillis();
System.out.println("map.values() time=\t" + (after - before));
before = System.currentTimeMillis();
// 遍历map中的值
Iterator<Integer> iteratorValues = map.values().iterator();
while (iteratorValues.hasNext()) {
iteratorValues.next();
//System.out.println("key = " + iterator.next());
}
after = System.currentTimeMillis();
System.out.println("map.values().iterator() time=\t" + (after - before));
}
/**
* 2(2)keySet get
* 根据键找值,效率很低
* @param map
*/
public void keySetForValueTest(Map<Integer, Integer> map){
long before = System.currentTimeMillis();
//遍历map中的键
for (Integer key : map.keySet()) {
Integer value = map.get(key);
//System.out.println("Key = " + key + ", Value = " + value);
}
long after = System.currentTimeMillis();
System.out.println("map.keySet() -> map.get(key) time=\t" + (after - before));
}
3、通过迭代器 map.entrySet().iterator()
/**
* 3(1)iterator type
* 迭代器 带泛型
* @param map
*/
public void iteratorTypeTest(Map<Integer, Integer> map){
long before = System.currentTimeMillis();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Integer, Integer> entry = entries.next();
Integer key = entry.getKey();
Integer value = entry.getValue();
//System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
long after = System.currentTimeMillis();
System.out.println("map.entrySet().iterator() time=\t" + (after - before));
}
4、map.forEach 注意:java8 才支持
/**
* 4 forEach 遍历的是键值,所以是两个参数
* forEach java8 lambda
* @param map
*/
public void forEachTest(Map<Integer, Integer> map){
long before = System.currentTimeMillis();
//map.forEach( (key,value) -> {System.out.println("Key = " + key+ ", Value = "+ value);} );
map.forEach( (key,value) -> {} );
long after = System.currentTimeMillis();
System.out.println("map.forEach time=\t" + (after - before));
// 一条语句可以省略{}
//map.forEach( (key,value) -> System.out.println("Key = " + key+ ", Value = "+ value) );
}
5、map.entrySet().stream().forEach 注意:java8 才支持
/**
* 5 stream forEach 遍历的是entry 所以是一个参数
* stream forEach java8 lambda
* @param map
*/
public void streamForEachTest(Map<Integer, Integer> map){
long before = System.currentTimeMillis();
//map.entrySet().stream().forEach( (entry) -> {System.out.println("Key = " + entry.getKey()+ ", Value = "+ entry.getValue());} );
//map.entrySet().stream().forEach( System.out::println);
map.entrySet().stream().forEach( (entry) -> {} );
long after = System.currentTimeMillis();
System.out.println("map.entrySet().stream().forEach time=\t" + (after - before));
// 一个参数可以省略() 一条语句可以省略{}
//map.entrySet().stream().forEach(entry -> System.out.println("Key = " + entry.getKey()+ ", Value = "+ entry.getValue()) );
}
String、String[]、ArrayList之间的转换
- ArrayList 转换为 String[]:
ArrayList list = new ArrayList<>();
list.add(“aaa”);
list.add(“bbb”);
String[] arrString = list.toArray(new String[list.size()]) ; - String[] 转换为 ArrayList:
ArrayList list = new ArrayList<> (new String[] { “aaa”, “bbb” }); - ArrayList 转换为 String:
ArrayList list = new ArrayList<>();
list.add(“aaa”);
list.add(“bbb”);
String str = String.join(“,”, list.toArray(new String[list.size()])); - String 转换为 ArrayList :
String str =”1,2,3,4,5”;
ArrayList b = new ArrayList( str.split(‘,’) ) ;
StringJoiner-字段串拼接
要高效拼接字符串,应该使用StringBuilder。
很多时候,我们拼接的字符串像这样:
// Hello Bob, Alice, Grace!
无法连接到Java代码运行助手。请检查本机的设置。
类似用分隔符拼接数组的需求很常见,所以Java标准库还提供了一个StringJoiner来干这个事:
import java.util.StringJoiner;
慢着!用StringJoiner的结果少了前面的”Hello “和结尾的”!”!遇到这种情况,需要给StringJoiner指定“开头”和“结尾”:
import java.util.StringJoiner;
那么StringJoiner内部是如何拼接字符串的呢?如果查看源码,可以发现,StringJoiner内部实际上就是使用了StringBuilder,所以拼接效率和StringBuilder几乎是一模一样的。
String.join()
String还提供了一个静态方法join(),这个方法在内部使用了StringJoiner来拼接字符串,在不需要指定“开头”和“结尾”的时候,用String.join()更方便:
String[] names = {“Bob”, “Alice”, “Grace”};
var s = String.join(“, “, names);
练习
请使用StringJoiner构造一个SELECT语句:
import java.util.StringJoiner;
public class Main {
public static void main(String[] args) {
String[] fields = { “name”, “position”, “salary” };
String table = “employee”;
String select = buildSelectSql(table, fields);
System.out.println(select);
System.out.println(“SELECT name, position, salary FROM employee”.equals(select) ? “测试成功” : “测试失败”);
}
}
下载练习:StringJoiner练习 (推荐使用IDE练习插件快速下载)
小结
用指定分隔符拼接字符串数组时,使用StringJoiner或者String.join()更方便;
用StringJoiner拼接字符串时,还可以额外附加一个“开头”和“结尾”。
RandomStringUtils工具类的使用/随机数
//产生5位长度的随机字符串,中文环境下是乱码
RandomStringUtils.random(5);
//使用指定的字符生成5位长度的随机字符串
RandomStringUtils.random(5, new char[]{‘a’,‘b’,‘c’,‘d’,‘e’,‘f’, ‘1’, ‘2’, ‘3’});
//生成指定长度的字母和数字的随机组合字符串
RandomStringUtils.randomAlphanumeric(5);
//生成随机数字字符串
RandomStringUtils.randomNumeric(5);
//生成随机[a-z]字符串,包含大小写
RandomStringUtils.randomAlphabetic(5);
//生成从ASCII 32到126组成的随机字符串
RandomStringUtils.randomAscii(4)
/*count 创建一个随机字符串,其长度是指定的字符数,字符将从参数的字母数字字符集中选择,如参数所示。
* letters true,生成的字符串可以包括字母字符
* numbers true,生成的字符串可以包含数字字符
*/
String random = RandomStringUtils.random(15, true, false);
/**
* 创建一个随机字符串,其长度是指定的字符数。
* 将从所有字符集中选择字符
*/
random = RandomStringUtils.random(22);
/**
* 创建一个随机字符串,其长度是指定的字符数。
* 字符将从字符串指定的字符集中选择,不能为空。如果NULL,则使用所有字符集。
*/
random = RandomStringUtils.random(15, “abcdefgABCDEFG123456789”);
/**
* 创建一个随机字符串,其长度是指定的字符数,字符将从参数的字母数字字符集中选择,如参数所示。
* count:计算创建的随机字符长度
* start:字符集在开始时的位置
* end:字符集在结束前的位置,必须大于65
* letters true,生成的字符串可以包括字母字符
* numbers true,生成的字符串可以包含数字字符
*/
random = RandomStringUtils.random(1009, 5, 129, true, true);
/**
* 产生一个长度为指定的随机字符串的字符数,字符将从拉丁字母(a-z、A-Z的选择)。
* count:创建随机字符串的长度
*/
random = RandomStringUtils.randomAlphabetic(15);
/**
* 创建一个随机字符串,其长度介于包含最小值和最大最大值之间,,字符将从拉丁字母(a-z、A-Z的选择)。
* minLengthInclusive :要生成的字符串的包含最小长度 * maxLengthExclusive :要生成的字符串的包含最大长度
*/
random = RandomStringUtils.randomAlphabetic(2, 15);
/**
* 创建一个随机字符串,其长度是指定的字符数,字符将从拉丁字母(a-z、A-Z)和数字0-9中选择。
* count :创建的随机数长度
*/
random = RandomStringUtils.randomAlphanumeric(15);
/**
* 创建一个随机字符串,其长度介于包含最小值和最大最大值之间,字符将从拉丁字母(a-z、A-Z)和数字0-9中选择。
* minLengthInclusive :要生成的字符串的包含最小长度
* maxLengthExclusive :要生成的字符串的包含最大长度
*/
random = RandomStringUtils.randomAlphanumeric(5, 68);
/**
* 创建一个随机字符串,其长度是指定的字符数,字符将从ASCII值介于32到126之间的字符集中选择(包括)
* count:随机字符串的长度
*/
random = RandomStringUtils.randomAscii(15);
/**
* 创建一个随机字符串,其长度介于包含最小值和最大最大值之间,字符将从ASCII值介于32到126之间的字符集中选择(包括)
* minLengthInclusive :要生成的字符串的包含最小长度
* maxLengthExclusive :要生成的字符串的包含最大长度
*/
random = RandomStringUtils.randomAscii(15, 30);
/**
* 创建一个随机字符串,其长度是指定的字符数,将从数字字符集中选择字符。
* count:生成随机数的长度
*/
random = RandomStringUtils.randomNumeric(15);
/**
* 创建一个随机字符串,其长度介于包含最小值和最大最大值之间,将从数字字符集中选择字符.
* minLengthInclusive, 要生成的字符串的包含最小长度
* maxLengthExclusive 要生成的字符串的包含最大长度
*/
random = RandomStringUtils.randomNumeric(15, 20);
//产生5位长度的随机字符串,中文环境下是乱码
RandomStringUtils.random(5);
//使用指定的字符生成5位长度的随机字符串
RandomStringUtils.random(5, new char[]{'a','b','c','d','e','f', '1', '2', '3'});
//生成指定长度的字母和数字的随机组合字符串
RandomStringUtils.randomAlphanumeric(5);
//生成随机数字字符串
RandomStringUtils.randomNumeric(5);
//生成随机[a-z]字符串,包含大小写
RandomStringUtils.randomAlphabetic(5);
//生成从ASCII 32到126组成的随机字符串
RandomStringUtils.randomAscii(4)
使用RandomStringUtils可以选择生成随机字符串,可以是全字母,全数字,自定义生成字符等等…
其最基础的方法:
参数解读:
count:需要生成的随机串位数
letters:只要字母
numbers:只要数字
chars:自定义生成字符数组,如果为null,则为所有字符
start、end:选择字符开始生成的位置——-如果chars为null,start就是ASCII你想开始生成字符的位置,end同理;chars不为空的话,就是你自定义字符数组开始生成字符的位置
random:随机源
1、random(int count) //在所有字符中随机生成6位
2、randomAscii(int count) //在ASCII表中的打印字符中,即ASCII表32-127中随机生成6位
3、randomAlphabetic(int count) // 生成只有字母的随机字符串,但是此方法的效率不高,不建议这样使用
4、randomAlphanumeric(int count) //生成只有字母和数字的随机字符串,同样不建议这样使用
5、randomNumeric(int count) // 生成只有数字的随机字符串,
6、random(int count, boolean letters, boolean numbers) //可以指定是否要限定只生成字母或数字,上述三个方法都是调用此方法
7、random(int count, int start, int end, boolean letters, boolean numbers) //可以指定字符集开始的位置,即不用搜索所有全部字符,同时可指定是否指定是否只生成字母或数字
8、random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) //用指定的字符集生成字符串
9、random(int count, String chars) //使用指定字符串的字符生成新的随机字符串
10、String random(int count, char[] chars) //用指定的字符集生成字符串,只是不能指定letters和numbers,其实还是调用了8