-1

I normally use C# and am not very familiar with Java API, but here is what I want to do:

I have two arrays:

String[] names = concertNames.toArray(new String[concertNames.size()]);
Double[] rates = concertRates.toArray(new Double[concertRates.size()]);

Each element from names corresponds to elements from rates, i.e. names[i] has a rate of rates[i].

I would like to get the names of N top-rated concerts. In C# I would use LINQ, and here, I'm not sure.

Edit: Off-topic? Are you people serious? I know how to sort an array, I just don't want to write 50 lines of horrible, rudimentary code in order to do a trivial thing.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Eutherpy
  • 4,471
  • 7
  • 40
  • 64
  • 3
    Please write at least 2 lines of code!!!!.. How it's possible this question has several upvotes! – Ele Dec 21 '17 at 22:34
  • Possible duplicate of [What is the Java equivalent for LINQ?](https://stackoverflow.com/questions/1217228/what-is-the-java-equivalent-for-linq) – Johan Witters Dec 21 '17 at 22:42
  • Why would you use parallel arrays instead of an array of objects holding `name` and `rate` for each concert? – Jim Garrison Dec 21 '17 at 22:56

3 Answers3

2

The neatest way I can think of is to stream the indexes, sort them by their rates and then map them to their names:

String[] topNames = 
    IntStream.range(0, rates.length)
             .boxed()
             .sorted(Comparator.comparing(i -> -1 * rates[i]))
             .limit(N)
             .map(i -> names[i])
             .toArray(String[]::new);
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • 1
    OP wants *"names of N top-rated concerts"*, so for `limit()` to retain top-rated concerts, the sort needs to be descending, e.g. `.sorted(Comparator.comparing((Integer i) -> rates[i]).reversed())`. – Andreas Dec 21 '17 at 22:48
  • @Andreas good catch, thanks. Edited and fixed. – Mureinik Dec 21 '17 at 22:49
  • @Mureinik `.sorted(Comparator.comparing(i -> rates[i]).reversed())` would be better. – Ousmane D. Dec 21 '17 at 22:50
  • Is it for developer readability that you use `-1 * rates[i]` instead of `-rates[i]`? – Andreas Dec 21 '17 at 22:50
  • @Aominè that was my first instinct too, but it messes up the type inference of `i`. You could use `(Integer i) -> ...` instead if `i -> ...`, of course, but that's a bit clunky, IMHO. – Mureinik Dec 21 '17 at 22:52
  • @Andreas yup, indeed. – Mureinik Dec 21 '17 at 22:52
1

Considering there is a relationship between an element in names and an element in rates I'd suggest you create a class to encapsulate these two fields, therefore, making it both easier to sort the objects based on the rate and also maintaining related data.

Another option would be to create a Map<String, Double> where each name is mapped to its corresponding rate.

if you decide to proceed with the first suggestion of creating your own class to encapsulate the two said fields you can accomplish the task like this:

NameOfClass[] topRated = myList.stream()
                .sorted(Comparator.comparingDouble(NameOfClass::getRate).reversed())
                .limit(10) // Top N
                .toArray(NameOfClass[]::new);

if you decide to proceed with the suggested Map approach, something like this would suffice:

Map<String, Double> resultSet = myMap.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
       .limit(10) // Top N
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                         (oldValue, newValue) -> ... , LinkedHashMap::new));
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
0

The short answer: http://www.jinq.org. inq makes LINQ-style queries are available for Java

Johan Witters
  • 1,529
  • 11
  • 23