能够在 java 扫描仪中输入一个值和一个字符串以输出排名

Be able to enter a value, and a string in a java scanner to output a ranking

我正在尝试创建一个显示此内容的排名:

  1. int(value) - String(username)

(即使我输入30个值和30个昵称,总共十次)

这是我的工作代码:

public class Methods {


    private static final ArrayList<Double> nbAll = new ArrayList<>();
    private static final ArrayList<String> pseudoAll = new ArrayList<>();

    public static void test() {
        try (Scanner scanner = new Scanner(System.in)) {

            System.out.print(ANSI_RED + "Please enter the number of notes you want to calculate : ");
            double nb = scanner.nextInt();
            String pseudo = scanner.next();

            for (int i = 0; i < nb; i++) {
                double temp = scanner.nextDouble();
                nbAll.add(temp);
            }


            System.out.println("------------");
            System.out.println("Ranking: ");
            nbAll.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
            retry();
        }
    }

我试过:为了让第二个 for 循环强制在字符串中输入用户名,但它没有用,对于排名我还没有成功

所需操作的屏幕: https://i.imgur.com/0QlGHd8.png

在这种特殊情况下,我个人认为如果您使用 HashMap or Map Interface 来存储所需数据可能会好一些。对于这类事情来说,它是相当理想的,因为 User Name 应该是唯一的,并且可以用作 Key,Rank 作为 Value,因为有几个用户可能包含相同的排名值:

Map<String, Integer> map = new HashMap<>();

另一件可能让生活变得更轻松的事情是用户在用白色 space 或制表符或其他任何分隔的单行中输入排名和与该排名相关的用户名,因为示例:

Ranking #1:
Enter a Rank value followed by a User Name separated with space,
for example: 250 John Doe. Enter 'd' when done.
Your entry: --> |

当然需要进行验证以确保正确输入,但使用 String#matches() method and a small Regular Expression(正则表达式)这并不过分困难,例如:

if (!myString.matches("^\d+\s+.{1,}$")) {
    System.err.println("Invalid Entry! Try again...");
    System.err.println();
    myString = "";
    continue;
}

上面传递给 String#matches() 方法的正则表达式 "^\d+\s+.{1,}$" 所做的是验证提供的用户条目的第一个组件实际上是由一位或多位数字组成的整数值的字符串表示形式。然后它检查以确保至少有一个 whitespace 跟随该数值,然后在 space 之后它期望至少看到 1 (或更多) space(s) 之后的任何字符,本质上是用户名。当然,如果用户输入的数据不正确,则会发出无效输入警告,用户有机会再次尝试输入。

一旦 valid 输入被获取,数据现在当然需要 split在它可以应用于 Map Interface 对象之前,将其转换为各自的数据类型。这当然是用 String#split() 方法完成的:

String[] stringParts = myString.split("\s+");

这将创建一个名为 stringParts 的 String[] 数组。 \s+ 正则表达式告诉 split() 方法将字符串拆分为一个或多个 whitespaces ' '(或 Tabs \t、换行 \n、回车 Returns \r、换页 \f 和垂直制表 \x0B)。这几乎涵盖了用户所需条目的所有情况。

现在我们有了数组,我们知道该数组的第一个元素将是提供的排名值。我们想在添加到我们的 Map 之前将其转换为 Integer 数据类型,如下所示:

int rank = Integer.parseInt(stringParts[0]);

现在我们需要用户名。因为在此示例中,我们还允许使用多个名称,例如名字和姓氏,所以将这些名称加在一起以便从中创建一个用户名字符串需要更多的工作。请记住,我们在 whitespaces 上拆分了数据条目,因此如果有多个名称,我们可能在 stringParts[] 数组中包含两个以上的元素。我们需要构建 userName 字符串。我们使用 for 循环和 StringBuilder class 来执行此操作,例如:

String[] stringParts = tmp.split("\s+");
int rank = Integer.parseInt(stringParts [0]);
StringBuilder sb = new StringBuilder("");
for (int i = 1; i < stringParts .length; i++) {
    if (!sb.toString().isEmpty()) {
        sb.append(" ");
    }
    sb.append(stringParts [i]);
}
String userName = sb.toString();

好的...现在我们有了用户名,所以让我们确保具有该用户名的排名尚未包含在 地图:

if (map.containsKey(userName)) {
    System.err.println("A ranking for '" + userName 
                     + "' has already been supplied! Try again...");
    System.err.println();
    myString = "";
    continue;
}

如果我们通过这一点那么一切都很好,我们可以将数据添加到 Map:

map.put(userName, rank);

这似乎有点冗长,但在我看来,事实并非如此。以下是一个工作示例或以上所有使用的示例:

Scanner userInput = new Scanner(System.in);
Map<String, Integer> map = new HashMap<>();
    
int count = 0;
String tmp = "";
while (tmp.isEmpty()) {
    System.out.println("Ranking #" + (count+1) + ":");
    System.out.print("Enter a Rank value followed by a User Name separated "
            + "with space,\nfor example: 250 John Doe. Enter 'd' when done.\n"
            + "Your entry: --> ");
    tmp = userInput.nextLine();
    if (tmp.equalsIgnoreCase("d")) {
        break;
    }
    if (!tmp.matches("^\d+\s+.{1,}$")) {
        System.err.println("Invalid Entry! Try again...");
        System.err.println();
        tmp = "";
        continue;
    }
        
    String[] parts = tmp.split("\s+");
    int rank = Integer.parseInt(parts[0]);
    StringBuilder sb = new StringBuilder("");
    for (int i = 1; i < parts.length; i++) {
        if (!sb.toString().isEmpty()) {
            sb.append(" ");
        }
        sb.append(parts[i]);
    }
    String userName = sb.toString();
    if (map.containsKey(userName)) {
        System.err.println("A ranking for '" + userName 
                         + "' has already been supplied! Try again...");
        System.err.println();
        tmp = "";
        continue;
    }
    count++;
    map.put(userName, rank);
    tmp = "";
    System.out.println();
}

// Sort the map by RANK value in 'descending' order:
Map<String, Integer> sortedMap = map.entrySet().stream().sorted(Map.Entry.<String, 
        Integer>comparingByValue().reversed()).collect(java.util.stream.Collectors.toMap(Map.Entry::
        getKey, Map.Entry::getValue,(e1, e2) -> e1, java.util.LinkedHashMap::new));
    
// If you want the Rank values sorted in 'Ascending' order then use below instead:
/* Map<String, Integer> sortedMap2= map.entrySet().stream().sorted(Map.Entry.<String, 
        Integer>comparingByValue()).collect(java.util.stream.Collectors.toMap(Map.Entry::
        getKey, Map.Entry::getValue,(e1, e2) -> e1, java.util.LinkedHashMap::new));   */
    
// Display the rankings in Console Window:
System.out.println();
System.out.println("You entered " + count + " rankings and they are as follows:");
System.out.println();
    
// Table header
String header = String.format("%-4s %-15s %-6s", 
                              "No.", "User Name", "Rank");
System.out.println(header);
// The header underline
System.out.println(String.join("", java.util.Collections.nCopies(header.length(), "=")));
// The rankings in spaced format...
count = 1;
for (Map.Entry<String,Integer> enties : sortedMap.entrySet()) {
    System.out.printf("%-4s %-15s %-6d %n", 
                      String.valueOf(count) + ")", 
                      enties.getKey(), 
                      enties.getValue());
    count++;
}

当上述代码为运行时,要求用户提供排名值和与该排名相关的用户名。然后要求用户输入一个又一个,直到该用户输入 'd'(对于 done)。提供的所有条目随后以 table 类型格式显示在控制台 Window 中。地图中的排名在显示之前已经按照降序排列(最高排名在前)。如果您更喜欢升序,那么还提供了该代码,但目前已被注释掉。