He estado tratando de conseguir que esto funcione, pero no estoy muy seguro de dónde voy mal. Se va a hacer sentido con el caso de prueba en un rato. Algunas cosas sobre lo que estoy haciendo. La lista debe tener una o más líneas. Si no hay al menos una línea, una IllegalArgumentException es lanzada. Cada línea tiene algún tipo de cadena, entonces un carácter de tabulación, a continuación, un doble, a continuación, una nueva línea. Si las líneas no siguen este patrón, a continuación, una IllegalArgumentException también sería lanzado. Esto está muy bien supone que funciona si ha realizado cualquier número de listas, así que por eso he tratado de esta manera
Básicamente, el programa se supone que para obtener una lista, diga algo como ...
California 6
Nevada 11
California 1
California 14
Arizona 21
Utah 2
California 7
Utah 10
Nevada 3
Utah 2
y debe devolver algo como esto:
California {6, 1, 14, 7}
Arizona {21}
Utah {2, 10, 2}
Nevada {11, 3}
Tenga en cuenta que yo sólo utilizamos cuatro en aras del ejemplo. Estoy tratando de conseguir que por lo que es el trabajo con cualquier número de listas. Aquí está mi código ...
public static TreeMap<String, ArrayList<Double>> readTable (Scanner dataSource)
{
ArrayList<String> dataFromFile = new ArrayList<String>();
while(dataSource.hasNext()){
dataFromFile.add(dataSource.next());
}
//Populate TreeMap
ArrayList<Double> statePopData = new ArrayList<>();
TreeMap<String, ArrayList<Double>> map = new TreeMap<>();
for (int i = 0; i < dataFromFile.size(); i++) {
boolean isDouble;
String state = "";
try {
Double.parseDouble(dataFromFile.get(i));
isDouble = true;
} catch (NumberFormatException | NullPointerException nfe) {
isDouble = false;
}
if(isDouble) {
statePopData.add(Double.parseDouble(dataFromFile.get(i)));
} else { //means its a string
statePopData.clear();
state = dataFromFile.get(i);
}
if (statePopData.isEmpty()) {
map.put(state, statePopData);
}
} return map;
}
Quiero evitar un mismo valor para todo, para todos los demás estados de la lista y estoy confundido en cuanto a por qué ocurre esto.
Aquí está el caso de la prueba he mencionado antes ...
@Test
public void testReadTable ()
{
try (Scanner scn = new Scanner(
"Utah\t10\nNevada\t3\nUtah\t2\nCalifornia\t14\nArizona\t21\nUtah\t2\nCalifornia\t7\nCalifornia\t6\nNevada\t11\nCalifornia\t1\n"))
{
TreeMap<String, ArrayList<Double>> actual = GraphingMethods.readTable(scn);
TreeMap<String, ArrayList<Double>> expected = new TreeMap<>();
ArrayList<Double> azList = new ArrayList<>();
azList.add(21.0);
expected.put("Arizona", azList);
ArrayList<Double> caList = new ArrayList<>();
caList.add(6.0);
caList.add(1.0);
caList.add(14.0);
caList.add(7.0);
expected.put("California", caList);
ArrayList<Double> nvList = new ArrayList<>();
nvList.add(11.0);
nvList.add(3.0);
expected.put("Nevada", nvList);
ArrayList<Double> utList = new ArrayList<>();
utList.add(2.0);
utList.add(10.0);
utList.add(2.0);
expected.put("Utah", utList);
assertEquals(expected, actual);
}
}
Soy un programador nuevo, por lo que cualquier consejo sería apreciado grandemente! Me encantaría saber lo que estoy haciendo mal para que yo pueda aprender más. :)
Creo que el problema principal es que se está modificando y la inserción de la misma ArrayList
instancia para cada estado. Una versión sencilla, sin comprobación robustez podría ser:
TreeMap<String, ArrayList<Double>> map = new TreeMap<>();
while (dataSource.hasNext()) {
String state = dataSource.next();
Double d = Double.parseDouble(dataSource.next());
map.computeIfAbsent(state, k -> new ArrayList<>()).add(d);
}
return map;
El computeIfAbsent
le permite añadir un nuevo ArrayList
cuando vea un nuevo estado (Java 8+).
Otra cuestión es la assertEquals
. Dado que los datos de lista número esperado es en un orden diferente que el real, el ArrayLists
no son iguales. Se podría verificar las claves y valores como la siguiente:
assertEquals(expected.keySet(), actual.keySet());
expected.forEach((state, list) -> {
Collections.sort(list);
Collections.sort(actual.get(state));
assertEquals(list, actual.get(state));
});