让Style帮你减少JAVA的错误

让Style帮你减少JAVA的错误

Style是一个java8的函数式工具集,但不仅仅包括函数式,还有许多常用类库的增强
首先给出Style工具集坐标
请在github中查看release
中文文档坐标1 坐标2
(如果好用请您点个星哦~)

本文通过java程序员常犯的10个错误这篇文章,以及本人平时编码中遭遇的失误,给出使用Style工具集后的解决方案

点击链接查看引用文章。后面给出的是部分译文

数组转换为数组列表

原文:

将数组转换为数组列表,开发者经常会这样做:

List list = Arrays.asList(arr);

Arrays.asList()将返回一个数组内部是私有静态类的ArrayList,这不是java.util.ArrayList类,java.util.Arrays.ArrayList类有set()、 get()、 contains()方法,但是没有任何加元素的方法,因此它的大小是固定的。你应该这么做来创建一个真正的数组:

ArrayList arrayList = new ArrayList(Arrays.asList(arr));

ArrayList的构造函数能够接受一个集合类型,这也是java.util.Arrays.ArrayList的超类。

Style的解法

这样构建无非是为了更可读,以及编写更少的代码。
Style提供更直观的方式:
例如:

List<String> list = $(new ArrayList<String>(), "apple", "banana", "coconut");

或者:

List<String> list=new ArrayList<>();
$(list).add("apple").add("banana").add("coconut");

检查一个数组包含一个值

原文:

开发者经常这么做:

Set set = new HashSet(Arrays.asList(arr));
return set.contains(targetValue);

代码可以工作,但是没有必要首先转换列表到Set,转换一个列表到一个Set需要额外的时间。因此你可以把它简化为:

Arrays.asList(arr).contains(targetValue);

for(String s: arr){
if(s.equals(targetValue))
    return true;
}
return false;

第一个比第二个更具可读性

Style的解法

更加具有可读性的操作:

// 直接获取
$(arr).findOne(e->e.equals(targetValue));

// 或者使用比jdk1.8更多功能的foreach循环
$(arr).forEach(e->{
    if(e.equals(targetValue))
        BreakWithResult(true);
    return false;
});

这两种增强不仅在数组上提供,在任何iterable对象上都提供。
这种方式也可进行更复杂的操作,比如判断元素的某个属性是否等于制定值等,一切都可以通过lambda自由掌控。

在一个循环中从一个列表里删除一个元素

原文:

考虑下面删除元素的代码在迭代中的结果:

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
for (int i = 0; i < list.size(); i++) {
    list.remove(i);
}
System.out.println(list);

输出是:

[b, d]

该方法有一个严重的问题,当一个元素被删除时,列表收缩的大小以及指针改变了。所以想要在循环内利用指针删除多个元素是无法正常进行的。
这种情况下使用迭代器才是正确的方法,foreach循环在Java中的工作像是一个迭代器,但实际上并不是,考虑下面的代码:

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
for (String s : list) {
    if (s.equals("a"))
        list.remove(s);
}

它会报出ConcurrentModificationException异常。
相反下面这个就可以正常工作。

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
Iterator iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();
        if (s.equals("a")) {
            iter.remove();
        }
}

.next()必须在.remove()之前被调用。在foreach循环中,编译器将在删除元素操作之后调用.next(),这也是导致ConcurrentModificationException异常的原因。

Style的解法

无需使用iterator,通过增强的foreach即可完成

$(list).forEach(e->{
    if(e.equals("a"))
        Remove();
});

更加可读,而且节约了代码量。

Mutable VS Immutable

原文:

Immutable对象有很多优势,比如简单、安全等等。但它要求每一个不同的值都需要有一个不同的对象,而太多的对象可能会导致垃圾收集的高成本。所以对Mutable和Immutable的选择应该有一个平衡点。
一般来说,Mutable对象用于避免产生过多的中间对象,经典的例子是连接大量的字符串数。如果你使用Immutable字符串,那么会产生很多符合垃圾收集条件的对象。这对CPU是浪费时间和精力的,当其可以使用Mutable对象作为正确的解决方案。(如StringBuilder)

String result="";
for(String s: arr){
    result = result + s;
}

这里还有一些其他Mutable对象可取的情况。例如mutable对象传递到方法中允许你在不跳过太多语法的情况下收集多个结果。另一个例子是排序和过滤,你可以构建一个带有原有集合的方法,并返回一个已排序的,不过这对大的集合来说会造成更大的浪费。

Style的解法

Style提供readOnly功能,可以轻松让一个带接口的对象变为只读对象。详情请见文档。
例如

List<String> readOnlyList=readOnly(list);
readOnlyList.get(0); // 可以正常执行
readOnlyList.add("durian"); // 将抛出异常

头疼的Null值

实际上,null值常常出现。一般来说我们可以先判断它是否为空,若为空则初始化这个变量。
比如

if(null==value)
    value="hello world";
System.out.println(value);

Style的解法

Style提供avoidNull,你可以这样实现上述代码:

System.out.println(avoidNull(value, ()->"hello world");
// 也可以更直接一些,把后面的lambda表达式换成字符串"hello world"

其他

Style中所有表达式和循环都带有返回值,比如if, switch, for, for-to-step, while, forEach/forThose等。大部分情况下他们可以让程序变得更简洁。

此外还有数十个好用的功能等你去发现~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值