JAVA编程技巧(六)

六、利用数据结构

6.1. 利用数组简化

对于固定上下限范围的 if-else 语句,可以用数组 + 循环来简化。

普通:

public static int getGrade(double score) {
    if (score >= 90.0D) {
        return 1;
    }
    if (score >= 80.0D) {
        return 2;
    }
    if (score >= 60.0D) {
        return 3;
    }
    if (score >= 30.0D) {
        return 4;
    }
    return 5;
}

精简:

private static final double[] SCORE_RANGES = new double[] {90.0D, 80.0D, 60.0D, 30.0D};
public static int getGrade(double score) {
    for (int i = 0; i < SCORE_RANGES.length; i++) {
        if (score >= SCORE_RANGES[i]) {
            return i + 1;
        }
    }
    return SCORE_RANGES.length + 1;
}

思考:上面的案例返回值是递增的,所以用数组简化是没有问题的。但是,如果返回值不是递增的,能否用数组进行简化呢?答案是可以的,请自行思考解决。

6.2. 利用 Map 简化

对于映射关系的 if-else 语句,可以用 Map 来简化。此外,此规则同样适用于简化映射关系的 switch 语句。

普通:

public static String getBiologyClass(String name) {
    switch (name) {
        case "dog" :
        return "animal";
        case "cat" :
        return "animal";
        case "lavender" :
        return "plant";
        ...
        default :
        return null;
    }
}

精简

private static final Map<String, String> BIOLOGY_CLASS_MAP
    = ImmutableMap.<String, String>builder()
    .put("dog", "animal")
    .put("cat", "animal")
    .put("lavender", "plant") 
    ...
    .build();
public static String getBiologyClass(String name) {
    return BIOLOGY_CLASS_MAP.get(name);
}

已经把方法简化为一行代码,其实都没有封装方法的必要了。

6.3. 利用容器类简化

Java 不像 Python 和 Go,方法不支持返回多个对象。如果需要返回多个对象,就必须自定义类,或者利用容器类。常见的容器类有 Apache 的 Pair 类和 Triple 类,Pair 类支持返回 2 个对象,Triple 类支持返回 3 个对象。

普通:

@Setter
@Getter
@ToString
@AllArgsConstructor
public static class PointAndDistance {
    private Point point;
    private Double distance;
}
 
public static PointAndDistance getNearest(Point point, Point[] points) {
    // 计算最近点和距离 
    ...
 
    // 返回最近点和距离 
        return new PointAndDistance(nearestPoint, nearestDistance);
}

精简:

public static Pair<Point, Double> getNearest(Point point, Point[] points) {
    // 计算最近点和距离 
    ...
 
    // 返回最近点和距离 
    return ImmutablePair.of(nearestPoint, nearestDistance);
}

6.4. 利用 ThreadLocal 简化

ThreadLocal 提供了线程专有对象,可以在整个线程生命周期中随时取用,极大地方便了一些逻辑的实现。用 ThreadLocal 保存线程上下文对象,可以避免不必要的参数传递。

普通:

由于 DateFormat 的 format 方法线程非安全(建议使用替代方法),在线程中频繁初始化 DateFormat 性能太低,如果考虑重用只能用参数传入 DateFormat。例子如下:

public static String formatDate(Date date, DateFormat format) {
    return format.format(date);
}
 
public static List<String> getDateList(Date minDate, Date maxDate, DateFormat format) {
    List<String> dateList = new ArrayList<>();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(minDate);
    String currDate = formatDate(calendar.getTime(), format);
    String maxsDate = formatDate(maxDate, format);
    while (currDate.compareTo(maxsDate) <= 0) {
        dateList.add(currDate);
        calendar.add(Calendar.DATE, 1);
        currDate = formatDate(calendar.getTime(), format);
    }
    return dateList;
}

精简

可能你会觉得以下的代码量反而多了,如果调用工具方法的地方比较多,就可以省下一大堆 DateFormat 初始化和传入参数的代码。

private static final ThreadLocal<DateFormat> LOCAL_DATE_FORMAT = new ThreadLocal<DateFormat>() {
    @Override
    protected DateFormat initialValue() {
        return new SimpleDateFormat("yyyyMMdd");
    }
};
 
public static String formatDate(Date date) {
    return LOCAL_DATE_FORMAT.get().format(date);
}
 
public static List<String> getDateList(Date minDate, Date maxDate) {
    List<String> dateList = new ArrayList<>();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(minDate);
    String currDate = formatDate(calendar.getTime());
    String maxsDate = formatDate(maxDate);
    while (currDate.compareTo(maxsDate) <= 0) {
        dateList.add(currDate);
        calendar.add(Calendar.DATE, 1);
        currDate = formatDate(calendar.getTime());
    }
    return dateList;
}

注意:ThreadLocal 有一定的内存泄露的风险,尽量在业务代码结束前调用 remove 方法进行数据清除。

正文完
 0
admin
版权声明:本站原创文章,由 admin 2016-01-10发表,共计3207字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处:https://www.mlzj.net。