Martin Peychev
Martin Peychev

Reputation: 1

How to sort a list of objects by number of times a substring is encountered in Java without using Comparator?

I have a Post class containing strings of text and titles and another class called Blog containing a List of Posts.I have created a method sorting all the posts containing a specified String and putting them into another List, but I can't figure out how to sort the second list by how many times each string occurs. I am not allowed to use the comparator class.

public class Post {
    private static int serialID = 0;
    private String title;
    private String text;
    Post(String title,String text){
        this.serialID++;
        this.text = text;
        this.title = title;
    }

    public String getText() {
        return text;
    }

    public String getTitle() {
        return title;
    }

    boolean checkIfContainedInTitle(String string){
        boolean isFound = title.contains(string);
        return isFound;
    }

    int checkTimesEncountered(String string){
        int M = string.length();
        int N = text.length();
        int res = 0;

        for (int i = 0; i <= N - M; i++) {

            int j;
            for (j = 0; j < M; j++) {
                if (text.charAt(i + j) != string.charAt(j)) {
                    break;
                }
            }
            if (j == M) {
                res++;
                j = 0;
            }
        }
        return res;
    }
}

How do I sort the strings so that I print the Post titles with the most frequently encountered substring?

public class Blog {
    private List<Post> postList;

    Blog(List<Post> postList){
        this.postList = postList;
    }

    void sortByTimesEncountered(List<Post> postList){
        List<Post> sortedPosts = null;
        for (Post post : postList){

        }
    }

    void printTitlesConatiningString(String string){ // this is the method I am struggling with
        List<Post> postList1 = null;
        List<Integer> postIndex = null;
        for(Post post : postList){
            if(post.getText().contains(string)){
                postList1.add(post);
            }
        }
        for(Post post : postList1){

        }


    }
}

Upvotes: 0

Views: 151

Answers (1)

tgallei
tgallei

Reputation: 859

You can use the Java-Stream-API and StringUtils from org.apache.commons.lang3:

Your Method would look like this:

void printTitlesConatiningString(String string){ 
    List<Post> postList1 = postlist.stream()
      .filter(p -> p.getText().contains(string)) // Collect all Posts that contains the string
      .sorted(Comparator.comparingInt(p -> StringUtils.countMatches(p.getText(), string))) // Sorts them by how many times each string occurs
      .collect(Collectors.toList()); // Collect them to a new List
}


EDIT:
OP has indicated that he has/would like to solve this problem without using Comparator. In this case I would extend the class post with a method to compare two posts.

private class Post{

    ...

    public int compareByStringCount(Post postToCompare, String string){
        return Integer.compare(StringUtils.countMatches(this.getText(), string), StringUtils.countMatches(postToCompare.getText(), string));
    }
}

the printTitlesConatiningString-Method kann use this new method to compare two posts. It would look like this:

void printTitlesConatiningString(String string){ 
    List<Post> postList1 = postlist.stream()
      .filter(p -> p.getText().contains(string)) // Collect all Posts that contains the string
      .sorted((p1, p2) -> p1.compareByStringCount(p2, s)) // Sorts them by how many times each string occurs
      .collect(Collectors.toList()); // Collect them to a new List
}

Personal note: as a matter of fact Comparator is still used here. But another solution is in my eyes much too complicated and not up to date.

Upvotes: 1

Related Questions