前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >揭秘Java编程中的可读性障碍:三个常见API的误区解析

揭秘Java编程中的可读性障碍:三个常见API的误区解析

作者头像
烟雨平生
发布2024-06-27 20:48:50
550
发布2024-06-27 20:48:50
举报
文章被收录于专栏:数字化之路数字化之路
  • Stream#filter:筛选的迷雾,你能知道哪些数据会留下?
  • Collections#sort:排序的顺序之谜,你能知道是升序还是降序?
  • ThreadPoolExecutor#shutdownNow:关闭的附加动作,你能知道除了shutdown还做了什么吗?
  • 小结:见名知意;单一职责

在Java编程的世界中,JDK提供了丰富的API来简化我们的任务。然而,并非所有的API都能直接传达其功能,有时它们甚至可能误导开发者。

本文将探讨JDK中的三个API,它们在命名和功能上可能给开发者带来困惑,并讨论如何通过改善命名和理解来提高代码的可读性。

Stream#filter:筛选的迷雾

java.util.stream.Stream#filter 是一个强大的方法,允许开发者对数据流进行筛选。然而,从方法名本身有歧义,这让我们无法直观地知道哪些数据会被保留:是true被过滤掉,还是保留?

这就需要我们去看API文档,如果能自己写demo,然后Run一下,就会记忆得更清楚。

代码语言:javascript
复制
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

/**
 * @Auther: cheng.tang
 * @Date: 2024/6/23
 * @Description: tool-box
 */
public class Java8StreamFilterTest {

    @Test
    public void streamFilterTest() {
        List<Integer> result = Stream.of(1, 2, 3).filter(i -> i > 1).collect(Collectors.toList());
        assertThat(result).isEqualTo(Arrays.asList(2, 3));
    }

}

在没Run之前,你能确定是pass还是fail呢?

剖析:这个java.util.stream.Stream#filter()有歧义,到底是满足什么条件才能留下呢?

改进建议:

使用java.util.stream.Stream#filterIfTrue来替代java.util.stream.Stream#filter

Collections#sort:排序的顺序之谜

java.util.Collections#sort 方法用于对集合进行排序,但方法名本身并没有明确指出是升序还是降序。这可能导致开发者在使用时产生疑惑,尤其是当集合元素的自然排序不是预期的顺序时。

代码语言:javascript
复制
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

/**
 * @Auther: cheng.tang
 * @Date: 2024/6/23
 * @Description: tool-box
 */
public class JavaCompareToTest {

    @Test
    public void compareToTest() {
        List<Integer> dataList = Arrays.asList(1, 20, 30, 100);
        Collections.sort(dataList, (o1, o2) -> o2.compareTo(o1));
        assertThat(dataList).isEqualTo(Arrays.asList(100, 30, 20, 1));
    }

}

在没有运行前,你能通过上面的代码,确定是passed还是fail呢?

Run:

当然一旦掌握了这种技能,填了坑,就会越来越“资深”。

不过,Java8中已经fix: dataList.sort(Comparator.reverseOrder());//降序 dataList.sort(Comparator.naturalOrder());//升序

代码语言:javascript
复制
    @Test
    public void compareToJava8Test() {
        List<Integer> dataList = Arrays.asList(1, 20, 30, 100);
        dataList.sort(Comparator.reverseOrder());
        assertThat(dataList).isEqualTo(Arrays.asList(100, 30, 20, 1));
        dataList.sort(Comparator.naturalOrder());
        assertThat(dataList).isEqualTo(Arrays.asList(1, 20, 30, 100));
    }

Run:

ThreadPoolExecutor#shutdownNow:关闭的附加动作

java.util.concurrent.ThreadPoolExecutor#shutdownNow 方法用于立即关闭线程池,并尝试停止所有正在执行的任务。然而,方法名并没有直接告诉我们它还会返回一个包含未执行任务的列表。

代码语言:javascript
复制
package com.tangcheng.toolbox.business.api;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadPoolApiTest {

    @Test
    public void testShutdownNow() throws InterruptedException {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        int totalThreadCount = 10;
        CountDownLatch exitController = new CountDownLatch(totalThreadCount);
        for (int i = 1; i <= totalThreadCount; i++) {
            // 产生一个任务,并将其加入到线程池
            String task = "task@ " + i;
            log.info("put {} ", task);
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    log.info(" begin task {} ", task);
                    try {
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException ignored) {
                        log.warn(" InterruptedException {} ", task);
                    }
                    log.info(" end task {} ", task);
                    exitController.countDown();
                }
            });
        }
        log.info("before invoke threadPool.shutdownNow() threadPool.getTaskCount() {} threadPool.getActiveCount() {} threadPool.getPoolSize() {}  ", threadPool.getTaskCount(), threadPool.getActiveCount(), threadPool.getPoolSize());
        List<Runnable> tasksShutdownNowReturn = threadPool.shutdownNow();
        log.info("after invoke threadPool.shutdownNow() threadPool.getTaskCount() {} tasksShutdownNowReturn.size {}  threadPool.getActiveCount() {}  threadPool.getPoolSize() {}  ", threadPool.getTaskCount(), tasksShutdownNowReturn.size(), threadPool.getActiveCount(), threadPool.getPoolSize());
        boolean awaitResult = exitController.await(3, TimeUnit.MINUTES);
        log.info("after await tthreadPool.getTaskCount() {} tasksShutdownNowReturn.size {}  threadPool.getActiveCount() {}  threadPool.getPoolSize() {} ", threadPool.getTaskCount(), tasksShutdownNowReturn.size(), threadPool.getActiveCount(), threadPool.getPoolSize());
        log.info(" awaitResult {} ", awaitResult);
    }


}

执行结果:

代码语言:javascript
复制
09:41:25.259 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 1 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 2 
09:41:25.265 [pool-1-thread-1] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  begin task task@ 1 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 3 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 4 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 5 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 6 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 7 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 8 
09:41:25.265 [pool-1-thread-2] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  begin task task@ 2 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 9 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 10 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - before invoke threadPool.shutdownNow() threadPool.getTaskCount() 10 threadPool.getActiveCount() 2 threadPool.getPoolSize() 2  
09:41:25.265 [pool-1-thread-2] WARN com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  InterruptedException task@ 2 
09:41:25.265 [pool-1-thread-1] WARN com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  InterruptedException task@ 1 
09:41:25.266 [pool-1-thread-2] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  end task task@ 2 
09:41:25.266 [pool-1-thread-1] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  end task task@ 1 
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - after invoke threadPool.shutdownNow() threadPool.getTaskCount() 2 tasksShutdownNowReturn.size 8  threadPool.getActiveCount() 2  threadPool.getPoolSize() 2  
09:44:25.270 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - after await tthreadPool.getTaskCount() 2 tasksShutdownNowReturn.size 8  threadPool.getActiveCount() 0  threadPool.getPoolSize() 0 
09:44:25.271 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest -  awaitResult false

可以看到:在执行 shutdownNow() 方法之后,首先会给所有线程池中的线程发送 interrupt 中断信号,尝试中断这些任务的执行,然后会将任务队列中正在等待的所有任务转移到一个 List 中并返回。

改进建议:

在调用此方法时,添加注释或使用更明确的命名,以避免混淆。

ThreadPoolExecutor#shutdownAndInterruptRunningThTaskNowAndRemoveAllWaitingTaskAndReturn()来替代ThreadPoolExecutor#shutdownNow

方法名是不是有点长了?是的,但命名不怕长,就怕一看就糊涂。

小结

良好的方法命名是代码可读性的关键。一个见名知意的方法名可以让其他开发者快速理解其功能和行为。此外,遵循单一职责原则,确保一个方法只做一件事,也是提高代码清晰度的有效手段。通过这些实践,我们可以减少误解,提高代码的可维护性和可读性。

“ 任何傻瓜都会编写计算机能理解的代码。 好的程序员能够编写人能够理解的代码。 ” 好代码的要求: 1、有意义的命名。 “见名知意”,代码要在字面上表达其含义,字面编程 2、单一职责。 每个函数、类、模块都专注于做一件事, 且这些函数、类、方法、实体等尽可能少 唐成,公众号:的数字化之路如果代码有段位,来看看你是什么段位?青铜?白银?还是黄金?【有源码】

在Java编程中,API的选择和使用直接影响到代码的质量和可维护性。通过深入理解JDK提供的API,并采用清晰、明确的命名和注释,我们可以编写出更加优雅、易于理解的代码。让我们共同努力,提升代码的可读性,为构建更加健壮和可维护的软件系统打下坚实的基础。

REFERENCE

线程池了解吗?说说线程池中 shutdown和shutdownNow的区别?

长开了呀

不知道从6月初的那一天开始,看到楼梯不想爬了,也不知道是因为走廊黑还是因为阶梯高

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在Java编程的世界中,JDK提供了丰富的API来简化我们的任务。然而,并非所有的API都能直接传达其功能,有时它们甚至可能误导开发者。
  • 本文将探讨JDK中的三个API,它们在命名和功能上可能给开发者带来困惑,并讨论如何通过改善命名和理解来提高代码的可读性。
  • Stream#filter:筛选的迷雾
  • Collections#sort:排序的顺序之谜
  • ThreadPoolExecutor#shutdownNow:关闭的附加动作
  • 小结
  • 在Java编程中,API的选择和使用直接影响到代码的质量和可维护性。通过深入理解JDK提供的API,并采用清晰、明确的命名和注释,我们可以编写出更加优雅、易于理解的代码。让我们共同努力,提升代码的可读性,为构建更加健壮和可维护的软件系统打下坚实的基础。
  • REFERENCE
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档