Как мне вернуть n количество исполнителей для данного жанра

#java

#java

Вопрос:

Вопрос в названии: у меня есть класс, который сопоставляет некоторых исполнителей с их соответствующим жанром. Считывает данные из текстового файла со строками, содержащими «жанр исполнителя», например, «ACDC Rock». В частности, у меня возникли проблемы с классом getArtists(String genre, int n). Как я могу вернуть n количество исполнителей в определенном жанре? Я предполагаю, что мне нужно создать цикл for от 0 до n, затем, если карта содержит этот жанр, каким-то образом верните исполнителей, но я не понимаю, как это сделать. Вот что я пробовал:

  public String getArtists(String genre, int n)
{   
   for (int i = 0; i <= n; i  ) {
       if (map.containsValue(genre)){
          
       }
  }
   return "";   
}
 

Вот остальная часть класса:

 public class Artists {

Map<String,String> map;

public Artists()
{
    map = new TreeMap<>();
}

public boolean readArtists(String textFile)
{
     Scanner file, lineScan;
     boolean success = true;
     try
     {
        file = new Scanner(new File(textFile));
        while (file.hasNext())
        {
           String line = file.nextLine();
           String[] parts = line.split(" ");
           map.put(parts[0].toUpperCase().replace('_',' '), parts[1]);
        }         
     }
     catch (FileNotFoundException exception)
     {
        success = false;
     }
     return success;
} 

public void addArtist (String artist, String genre) 
{
     map.put(artist.toUpperCase(), genre);
}

public void display()
{
     System.out.printf("%-30s %sn", "ARTIST", "GENRE");
     System.out.printf("%-30s %sn", "------", "-----");
     Set<String> artists = map.keySet();
     for (String artist: artists)
        System.out.printf("%-30s %sn", artist, map.get(artist));
}

 /**
       Returns a formatted list of at most n artists of the given genre.
      @param genre the genre of artists to be included 
      @param n the maximum number of artists to be included
      @return a list containing at most n artists of the given genre
 */
 public String getArtists(String genre, int n)
{   
   for (int i = 0; i <= n; i  ) {
       if (map.containsValue(genre)){
          
       }
    }
     return "";
 
 }

 public static void main(String[] args) 
 {    
   Artists artists = new Artists();
   artists.readArtists("artists30.txt");
   artists.addArtist("ACDC", "Rock");
    artists.display();
  System.out.println(artists.getArtists("Rock", 10));  
  System.out.println(artists.getArtists("Country", 10)); 
 }      
}
 

Комментарии:

1. Вы, конечно, хотите вернуть a List<String> , а не одну строку?

2. @BillCosby Пожалуйста, не меняйте принципиально свой вопрос после получения ответов. Это аннулирует время, потраченное другими на ответ на ваш вопрос.

Ответ №1:

Переберите всю карту, затем добавьте ключ (исполнителя) в список, когда найдете подходящий жанр

 List<String> result = new ArrayList<>();
map.forEach((k, v) -> {
    if (v.equals(genre) amp;amp; result.size() < n) result.add(k);
});
return resu<
 

Комментарии:

1. Не уверен, почему вы хотели бы использовать итератор… Конечно, вы можете использовать StringBuilder вместо списка, но в комментарии к методу явно указано «вернуть список». У вас может быть отдельный метод, который форматирует список в строку

2. Конечно, вы можете map.forEach заменить циклом over Iterator<Map.Entry> и List with StringBuilder . Логика остается той же

Ответ №2:

Я бы рекомендовал создать класс для исполнителей, который содержит информацию следующим образом:

     class ArtistInfo{
        String name;
        String genre;

        ArtistInfo(String name, String genre) {
            this.name = name;
            this.genre = genre;
        }
    }
 

и затем вы можете выполнить множество действий, таких как фильтр в списке массивов, например:

     ArrayList<ArtistInfo> ai = new ArrayList<>();
    ai.add(new ArtistInfo("ACDC", "Rock"));
    Stream<ArtistInfo> filteredList = ai.stream().filter(n -> n.genre.equals("Rock"));
 

а затем получить количество:

     long count = filteredList.count();
 

count это количество исполнителей с жанром «Рок».

Ответ №3:

Вероятно, у вас должно быть отображение из жанра в список исполнителей вместо сопоставления исполнителя с жанром, что-то вроде этого:

 Map<String,List<String>> map;
public void addArtist (String artist, String genre) 
{
  map.computeIfAbsent(genre, genre -> new LinkedList<>()).add(artist);
}
public List<String> getArtists(String genre, int n) {
  ArrayList<String> result = new ArrayList<>(n);
  List<String> mapList = map.get(genre);
  if (mapList == null)
    return resu<
  for (int i = 0; i < n amp;amp; i < mapList.size();   i)
    result.add(mapList.get(i));
}
 

Если вы хотите сохранить свою карту, вы также можете сделать что-то вроде:

 public List<String> getArtists(String genre, int n) {
  return map.entrySet().stream().filter(entry -> genre.equals(entry.getValue())).limit(n).map(entry -> entry.getKey()).collect(Collectors.toList());
}
 

Чтобы ответить на ваш комментарий, если вы хотите вернуть одну строку, вы можете сделать что-то вроде этого:

 public String getArtists(String genre, int n) {
  StringBuilder result = new StringBuilder();
  map.entrySet().stream().filter(entry -> genre.equals(entry.getValue())).limit(n).forEach(entry -> result.append(entry.getKey());
  return resu<
}
 

Или, поскольку я предполагаю, что вы новичок и можете не использоваться с потоками, простой способ, не такой оптимизированный, но может быть более понятным:

 public String getArtists(String genre, int n) {
  StringBuilder result = new StringBuilder();
  int count = 0;
  for (Map.Entry<String, String> entry : map.entrySet()) {
    if (count >= n)
      break; // if we already reach the limit n, stop the loop
    if (!genre.equals(entry.getValue())
      continue; // if this is not an artist of the genre we are looking for, skip it
    if (result.length() > 0)
      result.append(", "); // if this is not the first, add a comma so it is prettier
    result.append(entry.getKey()); // append the name of the artist
    count  ; // increment the counter
  }
  return resu<
}
 

Много способов 🙂

Ответ №4:

Вот простое решение. Мы сканируем все значения и сравниваем каждое значение с жанром и возвращаем первый n результат.

 public String getArtists(String genre, int n)
{
    List<String> artists = new ArrayList<>();
    map.forEach((key,value)-> {
        
        if(value.equals(genre)){
            if(artists.size() < n) artists.add(key);
        }
    });
    StringBuilder artistsAsString = new StringBuilder();
    for(String artist : artists){
        artistsAsString.append(artist).append(" ");
    }
    return artistsAsString.toString();

}