0

I have an issue with Maps. Supposing we have the code below:

public class HashMaps {
  public static void main(String[] ar){
    List<String> list = new ArrayList<>();
    Map<Integer, List<String>> myMap = new HashMap<>();
    list.add("one");
    list.add("two");
    list.add("three");
    list.add("four");
    List cloneList = ((List) ((ArrayList) list).clone());
    myMap.put(0, cloneList);
    list.clear();
    list.add("un");
    list.add("deux");
    list.add("trois");
    list.add("quatre");
    cloneList = ((List) ((ArrayList) list).clone());
    myMap.put(1, cloneList);
    System.out.println("map : "+myMap);
    System.out.println("keys : "+myMap.keySet());
    System.out.println("values : "+myMap.values());
  }
}

How could I get into a new List<String> all values (Lists) of myMap?

Essentially, I have lists like:

["one"]
["two"]
["three"]
["four"]

And want to get:

["one","two","three","four"]
nem035
  • 31,501
  • 5
  • 73
  • 88
Vassilis De
  • 363
  • 2
  • 17
  • 3
    You mean, **print them** one value per line instead of in the format of the standard `toString()` method of a list? There is no actual format underneath, the `toString()` method decides to print them like that. You can print them however you want – nem035 Dec 09 '14 at 17:09
  • 2
    There is some kind of "Attack of the clones" going on in this code :) –  Dec 09 '14 at 17:10
  • 1
    Please look at http://stackoverflow.com/questions/12887857/display-each-list-element-in-a-separate-line-console – Sualeh Fatehi Dec 09 '14 at 17:11
  • @nem I don't mean to print them. I mean to take all values from list separated. Even if I put them into another list, all I get from it is a list with all data as a group. I believe I made it more clear... – Vassilis De Dec 09 '14 at 17:15
  • @RC. indeed, tried to do without clones with no success! :-) – Vassilis De Dec 09 '14 at 17:16
  • @VassilisDe what do you mean by *take values separated*? What do you want to do with each individual String? – nem035 Dec 09 '14 at 17:17
  • I want to put it into a new List – Vassilis De Dec 09 '14 at 17:23
  • 1
    Don't use raw types. – Sotirios Delimanolis Dec 09 '14 at 17:24
  • 1
    @VassilisDe look at my answer, is that what you meant? – nem035 Dec 09 '14 at 17:24
  • @SotiriosDelimanolis any suggestions would be very wellcome – Vassilis De Dec 09 '14 at 17:30
  • @VassilisDe as far as Sotirios' comment, to understand what he meant check out [this](http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it) and [this](http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens) – nem035 Dec 09 '14 at 17:32
  • Thank you for your help guys – Vassilis De Dec 09 '14 at 17:33

2 Answers2

2

Based on your edit, it seems that you want to take each individual list in your Map and combine them into a single list:

List<String> combined = new ArrayList<String>();
for(List<String> list : myMap.values()) {
    combined.addAll(list);
}
// combined holds all lists into a single list

EDIT (based on your comment question)

If you want to add only certain lists, and not all of them, and the way you decide which ones is the index of list from the Map, then you can do it like this.

Convert the Collection returned by myMap.values() into a List and then use the list.get(index) method to add all values at allowed indexes.

List<String> selectedLists = new ArrayList<String>();
int[] allowedIndexes = {0, 1, 2, 3};                                          // only lists at indexes 0, 1, 2 and 3 are inserted into combined list
List<List<String>> listOfLists = new ArrayList<List<String>>(myMap.values()); // convert Collection to List
for(int i = 0; i < allowedIndexes.length; i++) {                              // if allowed index is within the bounds of the amount of lists, add the list at that index to selected lists
    int index = allowedIndexes[i];
    if(index < listOfLists.size()) {
        selectedLists.addAll(listOfLists.get(index));
    }
}
// selectedLists now contains only lists from the allowed indexes

A different approach would be to create an array of allowed indexes and iterate over all the values in the map, adding only the ones that correspond to an allowed index.

To determine if the current index is allowed, you can make a helper method that will iterate over all allowed indexes and check if current index exists as an allowed index.

Helper method:

// check if element exists in the array
boolean isInArray(int[] array, int element) {
    for(int i = 0; i < array.length; i++) {
        if(array[i] == element) {
            return true;
        }
    }
    return false;
}

Solution:

List<String> selectedLists = new ArrayList<String>();
int[] allowedIndexes = {0, 1, 2, 3};       // only lists at indexes 0, 1, 2 and 3 are inserted into combined list
int index = 0;                             // current index counter
for(List<String> list: myMap.values()) {   // iterate over all existing lists
    if(isInArray(allowedIndexes, index)) { // if the list at current index is allowed, add it to the selected lists
        selectedLists.addAll(list);
    }
    index++;                               // update the index
}
// selectedLists now contains only lists from the allowed indexes

One way you can improve the helper method, assuming you keep the array of allowed indexes sorted, is to use a Binary Search to check for existence of an index which would reduce the search time by a logarithmic factor:

boolean isInArrayImproved(int[] array, int element) {
    if(Arrays.binarySearch(array, element) >= 0) {
        return true;
    }
    return false;
}
nem035
  • 31,501
  • 5
  • 73
  • 88
  • Yes! That was exactly what I was looking for! Thank you so much! – Vassilis De Dec 09 '14 at 17:28
  • @mem is there any possibility to add into combined only those objects that refer to -let's say- the "first position" of map.values()? something like map.values.get(0) and then put those elements into the combined list? So combinedList has one, two, three, four and not all of them – Vassilis De Dec 09 '14 at 18:18
  • No problem, glad to help – nem035 Dec 10 '14 at 15:31
-2

Although I personally don't recommend it , you can simply Override your toString method.

A hack is something like this:

List<String> list = new ArrayList<String>(){

@Override
 public String toString(){
  String s="";
  for(String string : this){
    s= s + "\""+ string "\"\n";
  }
  return s;
 }
};

as people mentioned, the better way is to iterate through each element and print them out.

nafas
  • 5,004
  • 1
  • 23
  • 47
  • and how do I iterate every single element from every single list? – Vassilis De Dec 09 '14 at 17:16
  • @VassilisDe [http://stackoverflow.com/questions/12887857/display-each-list-element-in-a-separate-line-console](http://stackoverflow.com/questions/12887857/display-each-list-element-in-a-separate-line-console) – nafas Dec 09 '14 at 17:18