Listing words from text, provide lines where appears, count them I applied for Junior Java Developer in some company.
Got a task:"Listing words (without duplicates) from text, provide lines where appears, count them."
Output should looks like:

Alphacoronavirus - 3 - pozycje -> [1,3,2]

gatunki - 4 - pozycje -> [1,3,2,7]

Koronawirusy - 2 - pozycje -> [3,2]

Wirusów - 1 - pozycje -> [1]

Did not receive any feedback form them for two weeks so i will ask for judgment here.
Waiting for roast

Data structure:

import java.util.ArrayList;
import java.util.List;

public class PatternStats implements Comparable&lt;PatternStats&gt;{
    private String word;
    private int amountOfAppearances = 1;
    private List&lt;Integer&gt; linesContains = new ArrayList&lt;&gt;();

    public PatternStats(String word){
        this.word = word;
    }

    public String getWord() {
        return word;
    }

    public int getAmountOfAppearances() {
        return amountOfAppearances;
    }

    public List&lt;Integer&gt; getLinesContains() {
        return linesContains;
    }

    public void increaseAOA(){
        this.amountOfAppearances++;
    }

    public void addLineToList(int lineNO){
        this.linesContains.add(lineNO);
    }

    @Override
    public int compareTo(PatternStats o) {
        int compareInt = this.word.toLowerCase().compareTo(o.word.toLowerCase());
        if(compareInt &lt; 0) return -1;
        if(compareInt &gt; 0) return  1;
        return 0;
    }
}


WordLister

import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WordListingWithMap {

    private Map&lt;String, PatternStats&gt; patternStatsMap = new HashMap&lt;&gt;();

    public List&lt;PatternStats&gt; listWords(String filePath) {
        patternStatsMap.clear();
        String regex = "\\b[^\\d\\P{L}]+\\b";
        try {
            FileInputStream fis = new FileInputStream(filePath);
            Scanner sc = new Scanner(fis);
            scanTextCollectWords(sc, regex);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List&lt;PatternStats&gt; patternStats = new ArrayList&lt;&gt;(patternStatsMap.values());
        Collections.sort(patternStats);
        return patternStats;
    }

    private void scanTextCollectWords(Scanner sc, String regex) {
        int lineCounter = 0;
        while (sc.hasNextLine()){
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(sc.nextLine());
            lineCounter++;
            while (m.find()) {
                if (patternStatsMap.containsKey(m.group(0))) {
                    increaseExist(m.group(0), lineCounter);
                } else {
                    createNewAddToMap(m.group(0), lineCounter);
                }
            }
        }
    }

    private void createNewAddToMap(String word, int line) {
        PatternStats tempPatternStats = new PatternStats(word);
        tempPatternStats.addLineToList(line);
        patternStatsMap.put(word, tempPatternStats);
    }

    private void increaseExist(String word, int line) {
        if (!patternStatsMap.get(word).getLinesContains().contains(line))
            patternStatsMap.get(word).addLineToList(line);

        patternStatsMap.get(word).increaseAOA();
    }
}


and Main

import java.util.List;

public class Main {

    public static void main(String[] args) {
        final String filePatch = "C:\\vaTast\\src\\zadanie.txt";

        WordListingWithMap wlwm = new WordListingWithMap();
        toPrint = wlwm.listWords(filePatch);
        for (PatternStats each : toPrint){
            System.out.println(each.getWord() + " - " +
                    each.getAmountOfAppearances() + " - pozycje - &gt; " +
                    each.getLinesContains());
        }
    }
}


repo: https://github.com/krukarkonrad/vaRepo/
Your code and output are correct, for me there is a hint in the description of the task :


  Listing words (without duplicates) from text, provide lines where
  appears, count them.


For me the words without duplicates mean that a structure like Set well adapts to the constraint so instead of:


public class PatternStats implements Comparable&lt;PatternStats&gt;{
    private String word;
    private int amountOfAppearances = 1;
    private List&lt;Integer&gt; linesContains = new ArrayList&lt;&gt;();
}



you could define the PatternStats class the following way:

public class PatternStats implements Comparable&lt;PatternStats&gt;{
    private int amountOfAppearances;
    private SortedSet&lt;Integer&gt; linesContains; 
    private String word;

    public PatternStats(String word){
        this.amountOfAppearances = 1;
        this.linesContains = new TreeSet&lt;&gt;();
        this.word = word;
    }

    ...other methods
}


Your comparing method:

@Override
public int compareTo(PatternStats o) {
    int compareInt = this.word.toLowerCase().compareTo(o.word.toLowerCase());
    if(compareInt &lt; 0) return -1;
    if(compareInt &gt; 0) return  1;
    return 0;
}


can be rewritten in this way using compareToIgnoreCase:

@Override
public int compareTo(PatternStats o) {
    return word.compareToIgnoreCase(o.word);
}


You can override the toString method returning the output you expect so your class can be rewritten in this way :

PatternStats.java

public class PatternStats implements Comparable&lt;PatternStats&gt;{
    private int amountOfAppearances;
    private SortedSet&lt;Integer&gt; linesContains; 
    private String word;

    public PatternStats(String word){
        this.amountOfAppearances = 1;
        this.linesContains = new TreeSet&lt;&gt;();
        this.word = word;
    }

    public String getWord() {
        return word;
    }

    public int getAmountOfAppearances() {
        return amountOfAppearances;
    }

    public SortedSet&lt;Integer&gt; getLinesContains() {
        return linesContains;
    }

    public void increaseAOA(){
        ++amountOfAppearances;
    }

    public void addLineToSet(int lineNO){
        this.linesContains.add(lineNO);
    }

    @Override
    public int compareTo(PatternStats o) {
        return word.compareToIgnoreCase(o.word);
    }

    @Override
    public String toString() {
        return String.format("%s - %d - pozycje - &gt; %s", word, amountOfAppearances, linesContains);
    }

}


In your class WordListingWithMap you are reading a file line by line compiling and using the same regex for every line to match words: you can compile the regex one time like below:

public class WordListingWithMap {
    private static final String REGEX = "\\b[^\\d\\P{L}]+\\b";
    private static final Pattern PATTERN = Pattern.compile(REGEX);
    private int lineCounter;
    private Map&lt;String, PatternStats&gt; patternStatsMap;

    public WordListingWithMap() {
        this.patternStatsMap = new HashMap&lt;&gt;();
        this.lineCounter = 1;
    }

    ...other methods
}


Instead of reading a file using a FileInputStream you can use the Files class to make the code shorter like below:

WordListingWithMap.java

public class WordListingWithMap {
    private static final String REGEX = "\\b[^\\d\\P{L}]+\\b";
    private static final Pattern PATTERN = Pattern.compile(REGEX);
    private int lineCounter;
    private Map&lt;String, PatternStats&gt; patternStatsMap;

    public WordListingWithMap() {
        this.patternStatsMap = new HashMap&lt;&gt;();
        this.lineCounter = 1;
    }

    public List&lt;PatternStats&gt; listWords(String filePath) {
        try(Stream&lt;String&gt; lines = Files.lines(Paths.get(filePath))) {
            lines.forEach(l -&gt; scanTextCollectWords(l, lineCounter++));         
        } catch (IOException e) {
            e.printStackTrace();
        }
        List&lt;PatternStats&gt; patternStats = new ArrayList&lt;&gt;(patternStatsMap.values());
        Collections.sort(patternStats);
        return patternStats;
    }

    private void scanTextCollectWords(String line, int lineCounter) {
        Matcher m = PATTERN.matcher(line);

        while (m.find()) {
            String word = m.group(0);
            if (patternStatsMap.containsKey(word)) {
                increaseExist(word, lineCounter);
            } else {
                createNewAddToMap(word, lineCounter);
            }
        }
    }

    private void createNewAddToMap(String word, int line) {
        PatternStats tempPatternStats = new PatternStats(word);
        tempPatternStats.addLineToSet(line);
        patternStatsMap.put(word, tempPatternStats);
    }

    private void increaseExist(String word, int line) {
        patternStatsMap.get(word).addLineToSet(line);
        patternStatsMap.get(word).increaseAOA();
    }
}


Your Main class can be rewritten in this way:

Main.java

public class Main {

    public static void main(String[] args) {
        final String filePath = "zadanie.txt";

        WordListingWithMap wlwm = new WordListingWithMap();
        wlwm.listWords(filePath).forEach(System.out::println);
    }
}