哪位高人能帮我优化一段 Java 代码,强迫症犯了。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
hsiunien
V2EX    程序员

哪位高人能帮我优化一段 Java 代码,强迫症犯了。

  •  
  •   hsiunien 2017-08-13 03:17:05 +08:00 6610 次点击
    这是一个创建于 2983 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面这段 if 简直不能忍, 效果就是通过字符串 rec 把 studentsList 赋值,求一个优雅点的,健壮的写法。

     String rec = .... if (rec != null) { Student[] students = convert(rec); if (students.length != 0) { studentsList = Arrays.asList(students); } else { studentsList = new ArrayList<>(); } } else { studentsList = new ArrayList<>(); } 
    44 条回复    2017-08-31 00:46:31 +08:00
    pqee
        1
    pqee  
       2017-08-13 03:32:54 +08:00 via Android
    你这个就是最健壮的,最好维护的。不过优雅就完全没有了。
    luban
        2
    luban  
       2017-08-13 04:01:25 +08:00
    可以把这个移到最外层当作默认值 studentsList = new ArrayList<>();
    wangdongjie0101
        3
    wangdongjie0101  
       2017-08-13 04:14:19 +08:00
    我觉得排版对齐就可以,写成这样肯定很乱呀。学下 python 的对齐
    340244120
        4
    340244120  
       2017-08-13 05:46:08 +08:00
    ```
    String rec = ...
    if (rec != null && students.length != 0) {
    Student[] students = convert(rec);
    studentsList = Arrays.asList(students);
    } else {
    studentsList = new ArrayList<>();
    }
    ```
    340244120
        5
    340244120  
       2017-08-13 05:46:44 +08:00
    ```java
    String rec = ...
    if (rec != null && students.length != 0) {
    Student[] students = convert(rec);
    studentsList = Arrays.asList(students);
    } else {
    studentsList = new ArrayList<>();
    }
    ```
    340244120
        6
    340244120  
       2017-08-13 05:49:55 +08:00
    为啥没有 md 效果!
    netalpha
        7
    netalpha  
       2017-08-13 05:55:43 +08:00
    需要做一些改变,对你的方法. 去掉 if 唯一的优雅方式就是使用 java8.
    我猜你得 rec 应该可以被 split, 所以:
    rec.split(",")
    .map(
    str -> {
    new Student();
    }
    )
    .collect(
    Collections.toList();
    )

    之类的. 剩下自己研究吧.大概是这么个样子.
    GavinHao
        8
    GavinHao  
       2017-08-13 06:57:08 +08:00
    @340244120 你 students 杂就直接上判断了?
    zidian
        9
    zidian  
       2017-08-13 06:58:09 +08:00
    convert
    1. 能不能返回 List 而不是 Array ?
    2. rec 是 null 的时候,返回空的 List

    于是这段代码就变成一句话了

    studentsList = convert(rec);
    zjsxwc
        10
    zjsxwc  
       2017-08-13 07:10:06 +08:00
    ```
    Student[] students ;
    studentsList = new ArrayList<>();
    String rec = ....
    boolean isStudentExists = (rec != null) && (students = convert(rec)) && (students.length > 0);
    if (isStudentExists) {
    studentsList = Arrays.asList(students);
    }
    ```
    zjsxwc
        11
    zjsxwc  
       2017-08-13 07:14:31 +08:00
    感觉写 java 是最不需要带脑子的
    twm
        12
    twm  
       2017-08-13 08:26:35 +08:00 via iPhone
    换 scala 或 kotlin
    padeoe
        13
    padeoe  
       2017-08-13 08:30:23 +08:00
    如果 convert 函数不在其他地方使用,可以让 convert 函数直接返回 list ?
    其次,既然已经把 convert 返回的 Array 转成 List,一般是为了 List 的可变长,但 Arrays.asList(students)生成的 List 不是可变的,和 ArrayList 不大一样,要小心哦
    yuanfnadi
        14
    yuanfnadi  
       2017-08-13 08:37:48 +08:00 via iPhone
    @340244120 md 要四个点
    yuanfnadi
        15
    yuanfnadi  
       2017-08-13 08:47:30 +08:00
    ````java
    studentList = (rec != null && rec.length() > 0) ? Arrays.asList(covert(rec)) : new ArrayList<>();
    ````

    这样会不会不好维护? covert 里面要做好异常判断。
    而且返回结果一个是 list 一个是 arrayList 有点奇怪。
    M3oM3oBug
        16
    M3oM3oBug  
       2017-08-13 08:57:41 +08:00 via Android
    既然 convert 方法可以解析错误的 rec 信息(也就是根据错误的 rec 返回的 students 可能为空),何不在 convert 里面添加一行错误判断呢,也就是把 rec 是否为空加到 convert 里。
    话说我忘了 Arrays.asList 是否能接收空数组对象了,若能直接一行就 OK
    cwek
        17
    cwek  
       2017-08-13 09:29:44 +08:00
    String rec = ....
    studentsList=Collections.<>emptyList();
    if (rec != null) {
    Student[] students = convert(rec);
    if (students.length != 0) {
    studentsList = Arrays.asList(students);
    }
    }
    340244120
        18
    340244120  
       2017-08-13 10:05:30 +08:00
    @GavinHao 看 Dota2TI 熬了一星期的夜,视野模糊了
    @yuanfnadi 哈哈,讲道理就是三个点,可能只有主题才支持 md 吧。
    --------------------------------------------------------
    String rec = ...
    Boolean flag ;
    Student[] students;
    if (rec != null) {
    students = convert(rec);
    if (students.length != 0) {
    flag = true;
    }
    }
    if (flag){
    studentsList = Arrays.asList(students);
    } else {
    studentsList = new ArrayList<>();
    }
    hantsy
        19
    hantsy  
       2017-08-13 10:13:06 +08:00
    @netalpha 不错,终于看到有人用 Java8 了。
    myv2ex
        20
    myv2ex  
       2017-08-13 10:16:07 +08:00   1
    1.Arrays.asList 可以入空数组,convert 优化一下,可去除后续 if...else 判断,如果不优化,要做非 Null 判断
    2.空 List 构造可以用 Collections.EMPTY_LIST
    little_cup
        21
    little_cup  
       2017-08-13 10:18:35 +08:00 via Android
    Optional.ofNullable(…)
    .map(this::convert)
    .stream()
    .flatmap(Arrays::stream)
    .collect(Collectors.toList());

    这样?
    hantsy
        22
    hantsy  
       2017-08-13 10:28:49 +08:00
    就一数据转化而已。

    贴一段数据库初始化的代码,主要是用 Spring Data.

    ```
    this.posts
    .deleteAll()
    .thenMany(
    Flux
    .just("Post one", "Post two")
    .flatMap(
    title -> this.posts.save(Post.builder().title(title).content("content of " + title).build())
    )
    )
    .log()
    .subscribe(
    null,
    null,
    () -> log.info("done initialization...")
    );
    ```
    echotpq
        23
    echotpq  
       2017-08-13 10:38:41 +08:00
    楼主应该是处女座的
    msg7086
        24
    msg7086  
       2017-08-13 11:38:14 +08:00
    if (studentsList == null)
    studentsList = new ArrayList<>();
    inisun
        25
    inisun  
       2017-08-13 11:46:33 +08:00 via iPhone
    如果不是整个项目组都会用函数式编程,写 lambda 会被人唾弃吧。
    weakish
        26
    weakish  
       2017-08-13 11:56:10 +08:00
    `String rec`和`convert`不明确。`rec` 必然是有格式的。`convert`肯定不能转换任意字符串吧。
    所以 convert 实际做的是 parse 的活。

    如果`rec`包含的信息比较复杂,优先考虑用 JSON、CSV 之类通用格式,而不是特定的格式。
    因为要健壮,parser 肯定要处理校验,包括输出良好的报错,方便快速定位格式错误的地方。
    用通用格式,可以直接用现成的 parser (别人的代码,或者是自己积累的历史代码)。

    如果`rec`包含的信息非常简单,而且能保证不出现格式错误(比如 rec 本身就是通过程序生成的),
    那也可以自己写 parse 函数。
    但是`rec`的格式需要注明,
    或者是用长变量名,比如`rec`改成`spaceSeparatedNames`,
    或者是写注释。

    `convert`同样写长,比如 `parseStudents`.
    然后 `parseStudents` 直接返回 List 或 ArrayList
    ( Arrays.asList 和 new ArrayList 返回的类型是不同的,根据需求统一到一种),
    包括处理 students 为空的代码都是放到 `parseStudents` 函数里。

    另外,`parseStudents`一般拒绝 null,比如用 IntelliJ 的话,参数加 @NotNull
    同理,`rec`如果没有特别的理由,也拒绝 null。

    如果 IDE 不支持,写个检测 Object 是否 Null 的方法,`parseStudents` 先用这个函数检测参数,
    是 null 就报错,要嗦一点,效果也是一样的。
    mtus
        27
    mtus  
       2017-08-13 15:12:10 +08:00
    @padeoe 在 java 8 中, `Arrays.asList()` 是通过 `new ArrayList<>()` 实现的, 所以是可变的. 而 `Collections.EMPTY_LIST, Collections.emptyList(), Collections.singletonList()` 是不可变的.

    ```java
    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
    }
    ```
    zhx1991
        28
    zhx1991  
       2017-08-13 18:14:44 +08:00
    尽量提早 return, 减少 if 的层数是增加可读性的关键

    在外面 new 一个 list

    然后第一 if 要是 null 直接返回

    里面的判断也是一样的

    如果 students 是空, 直接返回

    最后一步才是赋值操作

    这样最后的代码只有一层 if, 至少看起来舒服很多
    sudit
        29
    sudit  
       2017-08-14 00:35:25 +08:00
    studentList = (rec == null)?new ArrayList<>() :
    Stream.of(rec.split(separator))
    .map(Student::convert)
    .collect(Collectors.toList());
    每个人都有对优雅的理解吧
    Chemist
        30
    Chemist  
       2017-08-14 01:11:47 +08:00
    ```java
    String rec = ...;
    do {
    if (null === rec) {
    studentsList = new ArrayList<>();
    break;
    }
    Student[] students = convert(rec);
    studentsList = students.length != 0 ?
    Arrays.asList(students)
    : new ArrayList<>();
    } while (false);
    ```
    cuebyte
        31
    cuebyte  
       2017-08-14 06:30:38 +08:00
    就这破代码,这么多人说没优化空间?写 Java 写傻了吧
    cuebyte
        32
    cuebyte  
       2017-08-14 06:41:13 +08:00
    首先这 convert 就很蠢,我就认为你们不能改 convert 好了……

    String rec = "...";
    List<Student> students = convertWrapper(rec);

    private List<Student> convertWrapper(String rec) {
    if (rec == null) return Collections.EMPTY_LIST;

    Student[] sbStudents = convert(rec);
    return Arrays.asList(sbStudents);
    }
    BBCCBB
        33
    BBCCBB  
       2017-08-14 08:42:16 +08:00   1
    @mtus 此 ArrayList 非彼 ArrayList, 这是 Arrays 的一个内部类,是不可变的
    BBCCBB
        34
    BBCCBB  
       2017-08-14 08:44:14 +08:00
    String rec = ....
    studentsList = null;
    if (rec != null) {
    Student[] students = convert(rec);
    if (students.length != 0) {
    studentsList = Arrays.asList(students);
    }
    }
    if(studentsList == null)
    studentsList = Collections.EMPTY_LIST();
    asj
        35
    asj  
       2017-08-14 10:29:58 +08:00
    这段代码的问题主要不在本身里面,其实你觉得不爽的地方就是空值处理。
    只需要修改 convert 函数保证不返回 null 即可。
    你本来的 if length != 0 就是没必要的, Arrays.asList 接受布丁不定长度参数,传入空数组是可以的。
    所以基本上可以简化为
    studentsList = Arrays.asList(convert(rec));
    vjnjc
        36
    vjnjc  
       2017-08-14 11:49:52 +08:00
    String rec = ....

    if (rec != null) {
    Student[] students = convert(rec);
    if (students.length != 0) {
    studentsList = Arrays.asList(students);
    }
    }
    if(studentsList == null) {
    studentsList = new ArrayList<>();
    }

    写成这样?

    不过我还是喜欢这种写法,

    if(XX==null){
    //异常处理
    }else{
    //业务逻辑
    }

    因为一般异常处理比较简单,所以写前面。
    yidinghe
        37
    yidinghe  
       2017-08-14 14:54:40 +08:00   1
    ![]( )
    这应该是楼主要的了。
    padeoe
        38
    padeoe  
       2017-08-14 16:26:03 +08:00   2
    @mtus 你在哪儿看到的这个说法...你看源码的吧,那是一个内部类,不是真ArrayList,所以是个大坑。
    bk201
        39
    bk201  
       2017-08-14 17:28:03 +08:00
    @cuebyte 讲句不好听的,你这改写还是很 low 啊,个人觉得这种情况最好的还是 java stream 处理方式
    liyu4
        40
    liyu4  
       2017-08-14 17:50:05 +08:00
    先处理 else
    wenzhoou
        41
    wenzhoou  
       2017-08-14 21:57:16 +08:00 via Android
    可不可以写个通用 method, 这样调用:this.<List<Student>>convertTo(rec, Student::convert)
    mtus
        42
    mtus  
       2017-08-16 00:08:56 +08:00
    @BBCCBB
    @padeoe
    感谢指正, 这个 Arrays 确实是一个内部类, 是不可变的...我在测试时可能脑子进水了...
    TestCode
        43
    TestCode  
       2017-08-18 17:09:18 +08:00
    String rec = ....
    studentsList = new ArrayList<>();
    if (rec != null) {
    Student[] students = convert(rec);
    if (students.length != 0) {
    studentsList.addAll(Arrays.asList(students));
    }
    }
    hsiunien
        44
    hsiunien  
    OP
       2017-08-31 00:46:31 +08:00
    Arrays.asList(students) 出来的确实是一个内部类,不可修改,Rx 大法确实简洁很多。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3208 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 12:07 PVG 20:07 LAX 05:07 JFK 08:07
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86