简体   繁体   English

接收比较器类类型

[英]Recieving Comparator Class type

I have two Comparators. 我有两个比较器。 One for sorting words by first letter (in sort used only for vowel words) 一个用于按首字母对单词排序(仅用于元音单词的排序)

public class FirstLetterComparator extends ComparatorType {
@Override
public int compare(String o1, String o2) {
    String upperObject1 = o1.toUpperCase();
    String upperObject2 = o2.toUpperCase();

    return upperObject1.charAt(0) - upperObject2.charAt(0);
  }
 }

Another for sorting by length/vowelsCount coef(used for all words in sort class) 另一个用于按长度/元音计数系数排序(用于排序类中的所有单词)

public class VowelColComparator extends ComparatorType {
String vowelGroup = "AEIOUaeiou";

@Override
public int compare(String o1, String o2) {
    int vCount1 = getVowelCount(o1);
    int vCount2 = getVowelCount(o2);

    float compareCoef1 = o1.length()/vCount1;
    float compareCoef2 = o2.length()/vCount2;

    return (int)(compareCoef1 - compareCoef2);
}

public int getVowelCount(String word){
    int vowelCount = 0;
    for (int i = 0; i < word.length(); i++){
        char ch = word.charAt(i);
        for (int j = 0; j < vowelGroup.length(); j++){
            char v = vowelGroup.charAt(j);
            if(ch == v)
                vowelCount++;
        }
    }
    return vowelCount;
}

And their superclass 和他们的超类

public class ComparatorType implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
    return 0;
  }
} 

In sort class i have two similar methods for sorting my list 在排序类中,我有两种类似的方法可以对列表进行排序

public class SortWords {

public static void sortVowelCol(String text, String regex){
    Scanner scanner = new Scanner(text);

    List<String> words = new ArrayList<>();

    System.out.println();
    System.out.println("Task1:");
    while (scanner.hasNext()){
        String word = scanner.next();
        if(word.matches(regex)){
            words.add(word);
        }
    }

    Collections.sort(words, new VowelColComparator());

    int lineCounter = 1;

    System.out.println();
    System.out.println();
    System.out.println("Sorted Words:");
    lineCounter = 1;
    for(String w : words){
        if(lineCounter == 12) {
            System.out.print(w + "\n");
            lineCounter = 0;
        }
        else
            System.out.print(w + " ");
        lineCounter++;
    }

}
public static void sortVowelWords(String text, String regex) {
    Scanner scanner = new Scanner(text);

    List<String> vowelWords = new ArrayList<>();

    System.out.println();
    System.out.println("Task2: ");
    while(scanner.hasNext()){
        String word = scanner.next();
        if(word.matches(regex)){
            vowelWords.add(word);
        }
    }

    Collections.sort(vowelWords, new FirstLetterComparator());

    System.out.println();
    System.out.println();
    System.out.println("Sorted List:");
    int lineCounter = 1;
    for(String w : vowelWords){
        if(lineCounter == 12) {
            System.out.print(w + "\n");
            lineCounter = 0;
        }
        else
            System.out.print(w + " ");
        lineCounter++;
    }
  }
 }

Main class 主班

public class Main {

public static void main(String[] args) {
    // write your code here
    SingletonText.getInstance().parse();
    SingletonText.getInstance().print();
      SortWords.sortVowelWords(SingletonText.getInstance().getText().toString(), "^[AEIOUaeiou].*");
    SortWords.sortVowelCol(SingletonText.getInstance().getText().toString(), "^[A-Za-z].*");
  }
 }

The quesuion is how can i make only one method instead of two similar methods in SortWords class? 问题是我怎样才能在SortWords类中仅制作一个方法而不是两个类似的方法? Or how to get comparator type in for Collections.sort argument? 或如何获取Collections.sort参数的比较器类型?

You may use a third parameter to define the comparator to use. 您可以使用第三个参数来定义要使用的比较器。

public static void sort(String text, String regex, ComparatorType comp) {
    // Code
    Collections.sort(words, comp);
    // Code
}

you need refactor two function like that: 您需要像这样重构两个函数:

public static void sortVowel(String text, String regex,Comparator comparator) {
    Scanner scanner = new Scanner(text);
    List<String> vowelWords = new ArrayList<>();

    System.out.println();
    System.out.println("Task2: ");
    while(scanner.hasNext()){
        String word = scanner.next();
        if(word.matches(regex)){
            vowelWords.add(word);
        }
    }

    Collections.sort(vowelWords, comparator);

    System.out.println();
    System.out.println();
    System.out.println("Sorted List:");
    int lineCounter = 1;
    for(String w : vowelWords){
        if(lineCounter == 12) {
            System.out.print(w + "\n");
            lineCounter = 0;
        }
        else
            System.out.print(w + " ");
        lineCounter++;
    }
  }
 }
public static void sort(String text, String regex, String sortType) {

  Collections.sort(words, sorttype.equals("Vowel") ? new VowelColComparator() : new FirstLetterComparator());

    // Your code

}

Then we can call like this 然后我们可以这样叫

SortWords.sort(SingletonText.getInstance().getText().toString(), "^[AEIOUaeiou].*", "Vowel");
SortWords.sort(SingletonText.getInstance().getText().toString(), "^[A-Za-z].*", "firstletter");

First of all your VowelColComparator.getVowelCount may fail due to division by zero when there is no vowel in given string. 首先,当给定字符串中没有元音时, VowelColComparator.getVowelCount可能会因除零而失败。 As you are comparing ratios of length and vowel count, you can do the following: 在比较长度和元音计数的比率时,可以执行以下操作:

float compareCoef1 = o1.length()/(vCount1+1);
float compareCoef2 = o2.length()/(vCount2+1);

You can use factory pattern in ComparatorType class. 您可以在ComparatorType类中使用工厂模式。 ie ComparatorType class will decide which instance (comparator) to use depending upon regex. ComparatorType类将根据正则表达式决定使用哪个实例(比较器)。 You can add as many comparators as you like. 您可以根据需要添加任意多个比较器。

public abstract class ComparatorType implements Comparator<String> {

    final public String vowelFirstLetterRegex = "^[A-Za-z].*";

    final public String vowelColRegex = "^[AEIOUaeiou].*]";


    public static ComparatorType getInstance(String regex) {
        if (regex.equals(vowelColRegex))
            return new VowelColComparator();
        else if(regex.equals(vowelFirstLetterRegex ))
            return new FirstLetterComparator();
        return null;
    }
}

And your SortWords class will have following method: 并且您的SortWords类将具有以下方法:

public static void sort(String text, String regex){
    Scanner scanner = new Scanner(text);

    List<String> words = new ArrayList<>();

    System.out.println();
    System.out.println("Task1:");
    while (scanner.hasNext()){
        String word = scanner.next();
        if(word.matches(regex)){
            words.add(word);
        }
    }

    Collections.sort(words, ComparatorType.getInstance(regex));

    int lineCounter = 1;

    System.out.println();
    System.out.println();
    System.out.println("Sorted Words:");
    lineCounter = 1;
    for(String w : words){
        if(lineCounter == 12) {
            System.out.print(w + "\n");
            lineCounter = 0;
        }
        else
            System.out.print(w + " ");
        lineCounter++;
    }

}

Well, as everyone said, you need to pass Comparator<String> as the third argument to your method: 嗯,正如大家所说,您需要将Comparator<String>作为第三个参数传递给您的方法:

sortVowelWords(String text, String regex, Comparator<String> cmp) {
    //...
}

I'd like to suggest some improvements to comparators themselves. 我想提出一些对比较器本身的改进。 Using lambda syntax, they may be written far more easily: 使用lambda语法,可以更轻松地编写它们:

static final Comparator<String> CMP_BY_FIRST_CHAR =
    Comparator.comparing(s -> Character.toUpperCase(s.charAt(0)));

static final Comparator<String> CMP_BY_VOWEL_COEF =
    Comparator.comparing(s -> 1f * s.length() / s.replaceAll("[^AEIOUaeiou]+", "").length());

In second comparator, I added explicit cast to float to handle possible infinity values properly. 在第二个比较器中,我添加了显式强制类型转换为float以正确处理可能的无穷大值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM