[ Java ] 方法里有很多判断需要提前结束,很多重复代码,求大神!

2021-10-21 13:56:21 +08:00
 nicepink

因为几个查询条件耗时久查到结果就提前结束,但是有重复的地方觉得不够优雅 if 判断那一块

    private void prepareBookingOffice(BrChangedEvent brChangedEvent) {
        BrGeneralInfoDto brGeneralInfoDto = Optional.ofNullable(brChangedEvent)
                .map(BrChangedEvent::getBrDto)
                .map(BrDto::getGeneralInfo)
                .orElse(BrGeneralInfoDto.builder().build());

        if (StringUtils.isNotEmpty(brGeneralInfoDto.getBookingOfficeCode())) {
            return;
        }

        // 耗时
        String officeCode = getOfficeCodeByOfficeUnlLocCode(brGeneralInfoDto);
        // 重复
        if (StringUtils.isNotEmpty(officeCode)) {
            brGeneralInfoDto.setBookingOfficeCode(officeCode);
            return;
        }

        // 耗时
        officeCode = getOfficeCodeByPor(brChangedEvent);
        // 重复
        if (StringUtils.isNotEmpty(officeCode)) {
            brGeneralInfoDto.setBookingOfficeCode(officeCode);
            return;
        }

        // 耗时
        officeCode = getOfficeCodeByFnd(brChangedEvent);
        // 重复
        if (StringUtils.isNotEmpty(officeCode)) {
            brGeneralInfoDto.setBookingOfficeCode(officeCode);
            return;
        }

        // 耗时
        officeCode = getOfficeCodeByPol(brChangedEvent);
        // 重复
        if (StringUtils.isNotEmpty(officeCode)) {
            brGeneralInfoDto.setBookingOfficeCode(officeCode);
        }
    }
3135 次点击
所在节点    程序员
23 条回复
itning
2021-10-21 13:59:57 +08:00
封装 继承 多态
aguesuka
2021-10-21 14:03:37 +08:00
把耗时函数改成 lambda 保存到 List 中
zoharSoul
2021-10-21 14:07:07 +08:00
没什么问题 挺好看懂的
zsl199512101234
2021-10-21 14:11:03 +08:00
二楼的方法,把耗时函数改成 lambda 保存到 list 中去,然后循环调用直到不为空就赋值并且 break
zjsxwc
2021-10-21 14:12:18 +08:00
for 循环遍历 List
chendy
2021-10-21 14:12:33 +08:00
第一步,把“取 officeCode”抽出去,如果方法不是很多而且也不怎么调整,做到这里就可以了

private String getOfficeCode(BrChangedEvent e){
String code = findOfficeCodeByA(e);
if (!StringUtil.isEmpty(code)) {
return code;
}
// 后面的差不多
}

如果方法比较多且需要调整,那么就进一步抽

private List<Function<BrChangedEvent, String>> codeFinders;

{
codeFinders.add(this::findOfficeCodeByA);
codeFinders.add(this::findOfficeCodeByB);
codeFinders.add(this::findOfficeCodeByC);
}


private String getOfficeCode(BrChangedEvent e) {
for(Function<BrChangedEvent, String>> finder : codeFinders) {
String code = finder.apply(codeFinders);
if(!StringUtil.isEmpty(code)){
return code;
}
return null;
}
}
admol
2021-10-21 14:12:42 +08:00
如果你只是觉得 if 有点多,给你提供一个思路,你看是否可行

public static void main(String[] args){
String officeCode = null;
if(Objects.nonNull(officeCode = a()) || Objects.nonNull(officeCode = b())|| Objects.nonNull(officeCode = c())){
}else{
officeCode = "default value";
}
System.out.println("officeCode:"+officeCode);
}

private static String c(){
System.out.println("C");
return "C";
}
private static String b(){
System.out.println("B");
return "B";
}

private static String a(){
System.out.println("A");
return null;
}
zsl199512101234
2021-10-21 14:14:31 +08:00
```java
@FunctionalInterface
public interface OfficeCodeService {
BookingOfficeCode getOfficeCode(BrGeneralInfoDto brGeneralInfoDto);
}
```
mango88
2021-10-21 14:15:15 +08:00
耗时操作有优先级要求吗 ?

还是只要任一返回值就可以了 ? 如果是任一个操作返回就满足需求,可以试试用 CompletableFuture.anyOf()
uCharles
2021-10-21 14:15:48 +08:00
试试抽取之后用 Optional 来进行判断
mango88
2021-10-21 14:18:17 +08:00
@mango88 每一步耗时操作可能会有空值返回 这样就不行了。

理解错了,6L 的方案会好点。
ipwx
2021-10-21 14:18:21 +08:00
不懂 Java,伪代码

interface IAction { String run(); }

class GetOfficeCodeByOfficeUnlLocCodeAction implements IAction { ... };
class GetOfficeCodeByPorAction implements IAction { ... };

。。。


List<IAction> actions = {
new GetOfficeCodeByOfficeUnlLocCodeAction(...),
new GetOfficeCodeByPorAction(...)
};

for (action in actions) {
String officeCode = getOfficeCodeByOfficeUnlLocCode(brGeneralInfoDto);
// 重复
if (StringUtils.isNotEmpty(officeCode)) {
brGeneralInfoDto.setBookingOfficeCode(officeCode);
return;
}
}
wolfie
2021-10-21 14:20:26 +08:00
在 Optional 基础上,定义一个 OptionalWrapper 。

OptionalWrapper<T> or(Supplier<T> supplier)

可以链式调用。
Guiyanakuang
2021-10-21 14:23:14 +08:00
为了保证可读性不建议抽取保存到 list 里,只需要将重复部分独立为单个函数,每个函数返回 this,链式调用逻辑更清晰
wolfie
2021-10-21 14:31:14 +08:00
```
class OptionalChain<T> {

private T value;

private OptionalChain(T val) {
value = val;
}

public static <T> OptionalChain<T> of(Supplier<T> supplier) {
return new OptionalChain<>(supplier.get());
}

public OptionalChain<T> or(Supplier<T> supplier) {
if (value == null) {
value = supplier.get();
}
return this;
}

public T get() {
return value;
}

}
```
hingbong
2021-10-21 16:30:40 +08:00
```
public OptionalChain<T> or(Predicate<T> predicate, Supplier<T> supplier) {
if (predicate.test()) {
return this;
}
value = supplier.get();
}
```
判断条件也动态起来?
fkdog
2021-10-21 16:30:43 +08:00
将所有的 getOfficeCodeByXXX()包装成 Function,然后塞进一个 List 。
做 list 的迭代,执行 function.apply(),如果返回值非空,则 break 跳出迭代。

``` java
List<Function<BrChangedEvent,String>> funcs= Arrays.asList(
XXX::getOfficeCodeByOfficeUnlLocCode,
XXX::getOfficeCodeByPor,
XXX::getOfficeCodeByFnd,
XXX::getOfficeCodeByPol);
for(Function<BrChangedEvent,String> func:funcs){
String officeCode = func.apply(brGeneralInfoDto);
if(String.isNotEmpty(officeCode)){
brGeneralInfoDto.setBookingOfficeCode(officeCode);
}
}
```
NeroKamin
2021-10-21 17:10:37 +08:00
@wolfie 第一直觉也是把 function 放到 list 遍历,再看这个链式调用,明显感觉要好很多
yazinnnn
2021-10-21 20:05:04 +08:00
functions.stream()
.parallel()
.map(it -> it.apply(""))
.filter(StringUtils::isNotBlank)
.findFirst()
.orElse("");

这样?
oneisall8955
2021-10-21 20:54:46 +08:00
remark,这样优化也有意义也有意思,后面再添加就不断的 append 进去

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/809503

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX