views:

578

answers:

4

I am stuck here:

my input file:

123 456 789
872 727 282
123 838 831
818 833 939

Now, I need to save data in a hashmap, 2d array or any best possible alternative like this:

key    value
123 -> 456, 789, 838, 831
872 -> 727, 282
818 -> 833, 939

What is the best possible way (simple and optimized) to achieve this and using what?

I am trying Map<String, List> rawData = new HashMap<String, List>(); but with no success.

I am new to java. :)

+10  A: 
Map<String, List<String>> data = new HashMap<String, List<String>>();

void addValue(String key, String value) {
  if (!data.contains(key)) {
    data.put(key, new LinkedList());
  }
  data.get(key).add(value);
}

I'm not so sure about the exact names of the java methods but this should be mostly it. Each HashMap key points to a LinkedList which contains your options.

ruibm
I would consider using a Set instead of a List in case I don't want duplicates in the value collection
Yaneeve
Yes, keeping a duplicate is not acceptable in my req. So, set will be a better option?
zengr
@unknown, yes a Set will remove all duplicates for you. A LinkedHashSet will preserve insert ordering, but if you don't care about the order, use HashSet. If you want it sorted, use TreeSet.
Yishai
Commons-Collections MultiValueMap does that http://taypworm.com/node/81
mhaller
A: 

Now to combine your syntax and ruibm's syntax, just in case you want another perspective:

String key = "123";
String value = "456";
Map<String, ArrayList> rawData = new HashMap<String, ArrayList>();
if(!rawData.containsKey(key)){
  rawData.put(key, new ArrayList());
}
rawData.get(key).add(value);
needs to be formatted... but Jung provided some edits to original answer that resembles mine.
ok, that works fine for me, just one last question, when I compile the java file, it gives a WARNING:Note: filenae.java uses unchecked or unsafe operations.Note: Recompile with -Xlint:unchecked for details.because of this line:Data.put(key, new ArrayList());Is that a serious problem?
zengr
Your warning is because you're not using generics when instantiating the ArrayList.
Ubersoldat
A: 

Here's a fairly strict version mandating the following:

  • Each key and each value is a triple of digits
  • Each line must define a key and at least one value
  • Values repeated for the same key are not coalesced in the value list
  • Any amount of space is tolerated after each triple

The repeated allocation of the Matcher can be optimized to use Matcher#reset() instead, but with some loss in clarity.

private static <T extends Appendable> T collectLineInto(Reader source, T sink)
  throws IOException
{
  for (int read = source.read();
       -1 != read && '\n' != read;
       read = source.read())
  {
    sink.append((char)read);
  }
  return sink;
}


static Map<Integer, List<Integer>> read(Reader reader)
  throws IOException
{
  final Pattern head = Pattern.compile("(\\d{3}) +(\\d{3})(?: +|$)");
  final Pattern tail = Pattern.compile("\\G(\\d{3})(?: +|$)");
  final Map<Integer, List<Integer>> result =
    new HashMap<Integer, List<Integer>>();
  for (final StringBuilder buf = new StringBuilder(11);
       0 != collectLineInto(reader, buf).length();
       buf.setLength(0))
  {
    final Matcher m = head.matcher(buf);
    if (!m.lookingAt())
      throw new IOException("Encountered invalid entry");

    final Integer key = new Integer(m.group(1));
    List<Integer> values = result.get(key);
    if (null == values)
    {
      values = new LinkedList<Integer>();
      result.put(key, values);
    }
    values.add(Integer.parseInt(m.group(2)));
    m.usePattern(tail);
    while (!m.hitEnd())
    {
      if (m.find())
        values.add(Integer.parseInt(m.group(1)));
      else
        throw new IOException("Encountered invalid triple");
    }
  }
  return result;
}


static Map<Integer, List<Integer>> read(InputStream is, Charset cs)
  throws IOException
{
  return read(new InputStreamReader(is, cs));
}
seh
@seh Dude, you rock!
zengr
Thanks. I updated the `read()` function to detect and report invalid input data.
seh