Re: TreeMap/Comparator a mapping problem
Jeff Higgins wrote:
Hi,
When I run the following code
several output lines are not what I expect.
I expect:
1:1:7 [red, red]
1:32:18 [yellow]
7:11:20 [orange]
but get:
1:1:7 Why is dataByCoordinate.get(k)==null here?
1:32:18 Why is dataByCoordinate.get(k)==null here?
7:11:20 Why is dataByCoordinate.get(k)==null here?
Is there something wrong with my CoordinateComparator?
I think so. In the case c[0]==0, c[1]!=0 it always
returns 1. Hence 1:2:3 compares greater than 1:3:4, but
at the same time 1:3:4 compares greater than 1:2:3.
Do I not understand how TreeMap works?
Something else?
Is there an easier/better way of mapping my input to output?
Can I safely ignore the warning: Type safety: The expression
of type TestMapping.CoordinateComparator needs unchecked
conversion to conform to Comparator<? super String>
Try using Comparator<String> instead of raw Comparator,
and change the types of the compare() arguments from Object
to String.
Thanks
Jeff Higgins
import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeMap;
public class TestMapping {
public static void main(String[] args)
{
ArrayList<String> metCriteria = new ArrayList<String>();
metCriteria.add("black 1:1:1 1:1:1 1:1:2 1:1:2 1:1:3 13:13:1");
metCriteria.add("brown 13:13:1 14:20:21 16:5:7");
metCriteria.add("red 1:1:1 1:1:2 1:1:2 1:1:3 1:1:3 1:1:3 1:1:4" +
" 1:1:5 1:1:5 1:1:6 1:1:7 1:1:7 13:13:1 24:49:7");
metCriteria.add("orange 5:32:37 7:11:20 7:20:36 12:18:5 19:13:5");
metCriteria.add("yellow 1:7:14 1:32:18");
metCriteria.add("green 24:49:7 41:16:14");
metCriteria.add("blue 2:38:18 19:13:5");
metCriteria.add("violet 19:13:5 24:49:7 42:24:31 72:3:19");
metCriteria.add("gray 1:2:6 44:13:11 61:2:17 70:2:4");
metCriteria.add("white 1:2:6 9:9:9");
TreeMap<String,ArrayList<String>> dataByCoordinate =
new TreeMap<String,ArrayList<String>>(
new CoordinateComparator());
for(String line : metCriteria)
{
String[] a = line.split(" ",2);
String[] b = a[1].split(" ");
for(int i = 0; i < b.length; i++)
if(dataByCoordinate.containsKey(b[i]))
{
dataByCoordinate.get(b[i]).add(a[0]);
}
else
{
dataByCoordinate.put(b[i], new ArrayList<String>());
dataByCoordinate.get(b[i]).add(a[0]);
}
}
for(String k : dataByCoordinate.keySet())
{
if(dataByCoordinate.get(k) != null)
{
System.out.println(k + " " +
dataByCoordinate.get(k).toString());
}
else
{
System.out.println(k +
" Why is dataByCoordinate.get(k)==null here?");
}
}
}
static class CoordinateComparator implements Comparator
{
public final int compare ( Object o1, Object o2 )
{
String s1 = ((String) o1);
String s2 = ((String) o2);
String[] sa = s1.split(":");
long[] a = new long[3];
a[0] = Long.valueOf(sa[0]);
a[1] = Long.valueOf(sa[1]);
a[2] = Long.valueOf(sa[2]);
String[] sb = s2.split(":");
long[] b = new long[3];
b[0] = Long.valueOf(sb[0]);
b[1] = Long.valueOf(sb[1]);
b[2] = Long.valueOf(sb[2]);
long[] c = new long[3];
c[0] = signum(a[0] - b[0]);
c[1] = signum(a[1] - b[1]);
c[2] = signum(a[2] - b[2]);
if(c[0] < 0)
{
return -1;
}
else if(c[0]==0 && c[1]==0 && c[2]<0)
{
return -1;
}
else if(c[0]==0 && c[1]==0 && c[2]==0)
{
return 0;
}
else if(c[0]==0 && c[1]==0 && c[2]>0)
{
return 1;
}
else
{
return 1;
}
}
An easier way to write this might be
if (c[0] != 0)
return c[0];
if (c[1] != 0)
return c[1];
return c[2];
.... with the added benefit that it's easy to see the
Comparator contract is fulfilled.
static final int signum ( long diff )
{
if ( diff > 0 ) return 1;
if ( diff < 0 ) return -1;
else return 0;
}
}
}
--
Eric Sosman
esosman@acm-dot-org.invalid