Search code examples
javadeserializationxml-rpcxmlrpcclient

Removing duplicate results from a Map (Not techinally duplicate)


I'm using www.opensubtitles.org API to get subtitles using file hash. Now, my problem is that it returns all the available subtitles for that particular file.

for example: I get this result when I select one file to download subtitles

https://i.sstatic.net/m2tZM.png

The whole result is here: http://privatepaste.com/download/22bb756930

The only difference between them is subtitle id and subtitle download links rest everything is same.

Now my problem is that this result is only for 1 file but I'll be using multiple files so it's not possible to get the first most result and use it.

The code to retrieve the result is given below

    Map<?, ?> result = (Map<?, ?>) rpcClient.execute("SearchSubtitles", params);
    Object[] data = (Object[]) result.get("data");
    Map<?, ?>[] results = new Map<?, ?>[data.length];
    int i = 0;
    for (Object element : data) {
        results[i] = (Map<?, ?>) element; //storing it in map
        i++;
    }

Now what I want is that when I choose let's say 12 files I want only 1 result to be stored for each of them and not 3 in the above case.

I did got it working but my code clearly is not good. I wrote this at 3 in the morning and took me 5 minutes because my only goal was to get it working.

    Map<?, ?> result = (Map<?, ?>) rpcClient.execute("SearchSubtitles", params);
    Object[] data = (Object[]) result.get("data");
    Map<?, ?>[] results = new Map<?, ?>[data.length];
    int i = 0;
    for (Object element : data) {
        System.out.println(element);
        results[i] = (Map<?, ?>) element;
        i++;
    }
    List<String> idmbIDs = new ArrayList<String>();
    for (Map<?, ?> map : results) {
        String string = (String) map.get("IDMovieImdb");
        if (!idmbIDs.contains(string))
            idmbIDs.add(string); //stores distinct idmb ids.
    }
    List<String> removedIDMBids = new ArrayList<String>();
    for (String store : idmbIDs) {
        for (Map<?, ?> map : results) {
            if (store.contains((String) map.get("IDMovieImdb")) && !removedIDMBids.contains(store)) {
                removedIDMBids.add(store);
                fileDetails.add(map);
            }
        }
    }
    for (Map<?, ?> realResult : fileDetails) {
        System.out.println(realResult); <- this does what I want
    }

I want a better way to do something like this. It would be great if I can get the most downloaded subtitles using the (map.get("SubDownloadsCnt");

Any help would be appreciated. Pardon me if I'm not able to explain it properly. and please don't neg.


Solution

  • I would rather create a Subtitle class with equals overriden (@Override) (re implemented), and there I will discriminate where to objects are equals or not.

    Your Subtitle class will have all the properties that you get in the response, as SeriesIMDBParent, IDSubtitle, etc.

    On that object you can create a constructor (or method load) that receives a Map<?, ?>[] parameter which you will use to load the values to to object. Or you can be smarter and user the Dozer Mapping, that will help you to do this job automatically.

    And then your code will look something like:

        BeanMappingBuilder builder = new BeanMappingBuilder() {
            protected void configure() {
                mapping(Map.class, Subtitle.class, mapNull(false))
                .
                .
                .
            }
         }
    

    After configuring the mapping you will have to make it possible with:

    Map<String, Object> result = (Map<String, Object>) rpcClient.execute("SearchSubtitles", params);
    Subtitle subtitle = new Subtitle();
    mapper.map(result, subtitle)
    

    ;

    After this and having implemented the equals and hashCode methods, you will be able to use a Set<Subtitle> (for example) which will force the Set to have unique objects based on the criteria you implemented to differentiate between objects.