The program solves the following problem: there are several files with text, a stream is created for each file through the thread pool to open and read the file and compile a List<String> from the read text, then it is assumed to use the Map<String, Long> common for all streams to collect statistics as follows - the key (key) will be a string from the list, respectively, and the value (value) is 1, but if such a key is already present, i.e. in the list and in other lists there are identical strings, then increment the value by one
If the first file contains the lines "Hello", the second, respectively, two lines "Java" and "World", and the third file is "Hello", then the resulting map should look like this:
{"Hello"=2,"Java"=1, "World"=1} My implementation: Everything works correctly
In the makeStatistics () method, an instance of the class is created (Statistic), where the general map is located, then the makeStatistics () method uses the getFilesPaths () method to compute paths to files with the .txt extension and put them into a list, then creates a fixed pool of threads of the number of text files in the folder (1 file - 1 stream), then a loop creates instances of classes for the stream ReaderThread, an instance of the class (Statistic) with the general map and the path to the file is passed to its constructor
public ArrayList<Path> getFilesPaths() { ArrayList<Path> filesNames = null; try (Stream<Path> files = Files.walk(Paths.get("D:\\DIR"))) { filesNames= files .filter(file -> file.toString().endsWith(".txt")) .collect(Collectors.toCollection(ArrayList::new)); filesNames.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); } return filesNames; } public void makeStatistics() { Statistic statistic = new Statistic(); ArrayList<Path> logPaths = getFilesPaths(); ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(logPaths.size()); for (Path filePath : logPaths) { ReaderThread logReader = new ReaderThread(statistic, filePath); executor.execute(logReader); } executor.shutdown(); } The stream class looks like this; it simply reads the file, along the path passed to it and saves the lines to the list, then in the line statistic.setStatisticMap (textLines); the list is sent to change the general map in the class Statistic
public class ReaderThread implements Runnable { private Path filePath; private Statistic statistic; public ReaderThread(Statistic statistic, Path filePath) { this.filePath = filePath; this.statistic = statistic; } public Path getFile() { return filePath; } public void run() { List<String> textLines; try(Stream<String> lineStream = Files.newBufferedReader(filePath).lines()) { textLines = lineStream .collect(Collectors.toCollection(ArrayList::new)); statistic.setStatisticMap(textLines); } catch (IOException e) { e.printStackTrace(); } } And here is a class with a common map:
public class Statistic { private Map<String, Long> statisticMap; public Statistic() { statisticMap = new HashMap<>(); } public synchronized void setStatisticMap(List<String> logLines) { statisticMap = logLines.stream() .collect(Collectors.toMap(Function.identity(), v -> 1L, Long::sum)); System.out.println(statisticMap); } public Map<String, Long> getStatisticMap() { return statisticMap; } The program displays the correct result, but I am interested in how and in what place to get access to the already constructed general map (statisticMap), i.e. how and where to get access to statisticMap after it is formed flows and it will be filled?
makeStatistics()afterexecutor.shutdown();writeSystem.out.println(statistic.getMinuteStatisticMap());{} empty map will be displayed and it will be displayed before the threads start working - Capt. Somov pm