场景
Java中不可变容器的使用
Java工具库Guava的不可变集合和新集合类型Multiset、Multimap、BiMap、RangeSet、RangeMap等的使用示例:
Java工具库Guava的不可变集合和新集合类型Multiset、Multimap、BiMap、RangeSet、RangeMap等的使用示例_类似rangemap_霸道流氓气质的博客-CSDN博客
上面讲了在guava中的新集合类型,其中就包含不可变集合。
其应用场景
如果是应用内的接口方法,容器传参,返回容器时,尽量不要使用不可变容器,因为没法保证别人拿到你的返回容器后,
会对它进行什么操作。
如果对外提供返回结果,特别是null的场景,使用不可变的空容器优于返回null
不可变容器,用于全局公用资源,共享配置参数;多线程的数据传递时,属于比较合适的场景。
1、jdk原生提供了一些不可变容器,最大的特点就是不支持添加、删除、修改容器内的值。
Map<Object, Object> objectObjectMap = Collections.emptyMap();
List<Object> objects = Collections.emptyList();
Set<Object> objects1 = Collections.emptySet();
上面是常用的三个,通常当一个方式的返回结果定义为容器类型时,为了避免空指针异常,在返回空容器时,
会如此使用。除了上面这几个,还有
List<Integer> integerList = Collections.unmodifiableList(Arrays.asList(1, 2, 3));
//上面创建的List,就不支持set/remove等修改操作
//Collections.unmodifiableMap();
//Collections.unmodifiableSet();
2、Guava中不可变容器
ImmutableList<Integer> of = ImmutableList.of(1, 2, 3);
ImmutableSet<Integer> of1 = ImmutableSet.of(1, 2, 3);
ImmutableMap<String, Integer> of2 = ImmutableMap.of("badao", 11, "aa", 22);
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
Java中列表遍历删除的方式
1、迭代器删除
List<String> list = new ArrayList<String>(){
{
add("badao");
add("de");
add("cheng");
add("xv");
add("yuan");
}};
//1、迭代删除
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String tmp = iterator.next();
if(tmp.contains("de")){
iterator.remove();
}
}
System.out.println(list);
2、JDK8+ 流的方式实现列表遍历删除
list.removeIf(s -> s.contains("ba"));
System.out.println(list);
Java中HashMap遍历删除的方式
1、迭代器遍历
ap的迭代删除,和list,set不太一样,不能直接获取Iterator对象,提供的删除方法也是单个的,
根据key进行删除,如果需要将map中满足某些条件的元素删除掉,它的entrySet有,可以通过它来实现遍历删除
Map<String,Integer> map = new HashMap<String,Integer>(){
{
put("a",1);
put("b",3);
put("c",4);
put("d",6);
put("e",8);
}};
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
Map.Entry<String,Integer> entry;
while (iterator.hasNext()){
entry = iterator.next();
if((entry.getValue() & 1) == 0){
iterator.remove();
}
}
System.out.println(map);
2、到jdk8以后,针对容器提供了很多简洁的操作方式,迭代删除更简单
Map<String,Integer> map1 = new HashMap<String,Integer>(){
{
put("a",1);
put("b",3);
put("c",4);
put("d",6);
put("e",8);
}};
map1.entrySet().removeIf(entrySet->(entrySet.getValue() & 1) == 0);
System.out.println(map1);
Java中巧用函数方法实现二维数组遍历
二维数组遍历,每个元素判断是否为偶数
int[][] cells = new int[][]{
{1,2,3,4},{5,6,7,8},{9,10,11,12}};
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
//&1 与操作,等于0 是偶数,需要用括号包围
if((cells[i][j] & 1) ==0){
ans.add(cells[i][j]);
}
}
}
System.out.println(ans);
面的实现没啥问题,但是代码深度有三层,当if中再有其他的判定条件,
那么这个代码层级就很容易增加,如果是三维数据,一个遍历就是三层,再加其他逻辑,层数会更多
1、函数方法消减代码层级
定义一个函数方法,输入函数坐标,在这个函数体中执行我们的遍历逻辑即可
java8中常用函数式接口Supplier<T>、Consumer<T>、Function<T,R>、Predicate<T>使用示例:
参考上面教程
函数方法直接使用了JDK默认提供的BiConsumer,两个参数,都是int数组下标;无返回值。
BiConsumer函数式接口,表示一个带有两个参数(T,U)且不返回结果的操作。
public static void scan(int maxX, int maxY, BiConsumer<Integer,Integer> consumer){
for (int i = 0; i < maxX; i++) {
for (int j = 0; j < maxY; j++) {
consumer.accept(i,j);
}
}
}
那么上面的例子可以修改为
List<Integer> ans2 = new ArrayList<>();
scan(cells.length,cells[0].length,(i, j) -> {
if((cells[i][j] & 1) == 0)
ans2.add(cells[i][j]);
});
System.out.println(ans2);
相比于前面的,貌似只少了一层,但是当数组变成三维、四维以后,这个改动的写法层级不变
2、遍历中return支持
前面的对于正常的遍历没啥问题,但是当我们在遍历过程中,遇到某个条件直接返回,能支持吗
,比如遍历一个二维数组,判断其中是否有偶数,如果有则返回坐标。
可以在执行逻辑中添加一个额外的返回值,用于标记是否中断循环直接返回。
定义一个函数方法,接收循环的下标和返回值
当一个方法需要返回两个及以上字段时,我们一般会封装成一个临时对象返回,现在有了Pair就可以返回两个字段
首先自定义函数接口ScanProcess
import org.apache.commons.lang3.tuple.ImmutablePair;
@FunctionalInterface
public interface ScanProcess<T> {
ImmutablePair<Boolean,T> accept(int i, int j);
}
循环通用方法就可以相应的改成
public static <T> T scanReturn(int x,int y,ScanProcess<T> func){
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
ImmutablePair<Boolean,T> ans = func.accept(i,j);
if(ans != null && ans.left)
return ans.right;
}
}
return null;
}
上面的调用就可以修改为
int[][] cells3 = new int[][]{
{1,2,3,4},{5,6,7,8},{9,10,11,12}};
String s = scanReturn(cells3.length, cells3[0].length, (i, j) -> {
if ((cells3[i][j] & 1) == 0) {
return ImmutablePair.of(true, i + "_" + j);
}
return ImmutablePair.of(false, null);
});
System.out.println(s);