java - 将字符串从 InputStream 映射到 ExecutorService

标签 java java-8 java-stream inputstream iot

我正在实现我的DIY IoT。我有一个中央节点(服务器),它接收来自不同来源的命令并执行它们。

输入格式:

<DEVICE_NAME>_<COMMAND> <DEVICE_NAME>_<COMMAND>  <DEVICE_NAME>_<COMMAND>
<DEVICE_NAME>_<COMMAND>  <DEVICE_NAME>_<COMMAND> 
<DEVICE_NAME>_<COMMAND>  <DEVICE_NAME>_<COMMAND>  <DEVICE_NAME>_<COMMAND> 

每一行可能包含多个命令。

我已经实现了一个命令执行服务器,它将 session 中的命令作为 InputStream。然后我拆分数据并处理它:

private Device c0 = // Device constructor
private Device c1 = // Device constructor
private Device c2 = // Device constructor
private Device c3 = // Device constructor

private ExecutorService executor = Executors.newFixedThreadPool(3);

public void onConnection(InputStream in)     
    InputStreamReader isr = new InputStreamReader(in);
    LineNumberReader reader = new LineNumberReader(isr);

    String line = null;
    while ((line = reader.readLine()) != null) {
        String[] strings = line.split(",");
        for (String raw : strings) {
            String command = raw.substring(0, 3);
            if (raw.startsWith("C0_")) {
                executor.submit(() -> c0.execute(command));
            } else if (raw.startsWith("C1_")) {
                executor.submit(() -> c1.execute(command));
            } else if (raw.startsWith("C2_")) {
                executor.submit(() -> c2.execute(command));
            } else if (raw.startsWith("C3_")) {
                executor.submit(() -> c3.execute(command));
            }
        }
    }
}

我知道代码看起来很丑。你有什么改进的想法吗?也许我可以使用 Steam API? 感谢任何提示/建议。

更新

我试图通过只提交一次任务来清理代码,但编译器说 device 必须是 finaleffectively final 所以这是行不通的:

String command = raw.substring(0, 3);
Device device;
if (raw.startsWith("C0_")) {
    device = c0;
} else if (raw.startsWith("C1_")) {
    device = c1;
} else if (raw.startsWith("C2_")) {
    device = c2;
} else if (raw.startsWith("C3_")) {
    device = c3;
}
executor.submit(() -> device.execute(command));

最佳答案

你可以像这样映射你的命令:

InputStreamReader isr = new InputStreamReader(is);
BufferedReader buffReader = new BufferedReader(isr);

Map<String, List<String>> map = buffReader.lines()
            .map(s -> s.split(" "))
            .flatMap(Arrays::stream)
            .map(s -> s.split("(?<=_)", 2))
            .collect(groupingBy(p -> p[0], mapping(p -> p[1], toList())));

更新

实际上你可以结合映射和提交:

// Register your devices
Map<String, Device> devices = new HashMap<>();
devices.put("c0", c0);
devices.put("c1", c1);
devices.put("c2", c2);
devices.put("c3", c3);
...

public void onConnection(InputStream in) {
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader buffReader = new BufferedReader(isr);
    buffReader.lines()
              .parallel()
              .map(s -> s.split(" "))
              .flatMap(Arrays::stream)
              .map(s -> s.split("(?<=_)", 2))
              .forEach(p -> executor.submit(
                      () -> devices.get(p[0]).execute(p[1])
               ));
}

关于java - 将字符串从 InputStream 映射到 ExecutorService,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53269762/

相关文章:

Java 流 toArray() 转换为特定类型的数组

java - 从具有匹配名称的 List<Student> 中获取 Student 对象而不进行迭代 (Java)

仅使用运行时异常的 Java 数据对象规范?

java - 是否可以使用 GWT 在浏览器缓存中存储变量(最好是字符串)?

java - 如何用 lambda 表达式替换 WebDriverWait()?

Java 8 : How to get element at an index from a Stream

java - 通过properties在xml配置中配置spring bean抽象与否

java - 如何将对象映射到字符串中以使用 ObjectMapper 进行设置

java - 如何在eclipse便携版中设置jdk?

java - 使用 Java 8 流以函数式方式生成数组的连续总和