Java 中 Map 的5种遍历方式
同系列文章
java 中 List 的5种遍历方式
Java 中 Set 的4中遍历方式
Java 中 Map 的5种遍历方式
主测试方法
@Testpublic 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
