Java: La mayoría forma eficiente para recorrer los valores CSV y la suma de una columna para cada valor único en otra columna

FinDev:

Tengo un archivo CSV con 500.000 filas de datos y 22 columnas. Estos datos representan todos los vuelos comerciales en los EE.UU. por un año. Estoy siendo la tarea de encontrar el número de la cola del avión que voló más millas en el conjunto de datos. La columna 5 contiene el número de la cola del airplain para cada vuelo. Columna 22 contiene la distancia total recorrida.

Por favor, vea mi extractQ3método siguiente. En primer lugar, se creó una HashMappara toda la CSV utilizando el createHashMap()método. Entonces, me encontré con un forbucle para identificar cada número de la cola única en el conjunto de datos y los almacenan en una matriz llamada tailNumbers. Luego, para cada número de la cola única, yo bucle a través de la totalidad Hashmapde calcular el total de millas de distancia para que el número de cola.

El código funciona muy bien en conjuntos de datos más pequeños, pero una vez que el tamaño se incrementó a 500.000 filas del código se vuelve terriblemente ineficiente y lleva una eternidad para funcionar. ¿Alguien puede ofrecerle una manera más rápida de hacer esto?

public class FlightData {

    HashMap<String,String[]>  dataMap;

        public static void main(String[] args) {

            FlightData map1 = new FlightData();
            map1.dataMap = map1.createHashMap();

            String answer = map1.extractQ3(map1);  
}

        public String extractQ3(FlightData map1) {
            ArrayList<String> tailNumbers = new ArrayList<String>();
            ArrayList<Integer> tailMiles = new ArrayList<Integer>();
            //Filling the Array with all tail numbers
            for (String[] value : map1.dataMap.values()) {
                if(Arrays.asList(tailNumbers).contains(value[4])) {  
                } else {
                    tailNumbers.add(value[4]);
                }
            }

            for (int i = 0; i < tailNumbers.size(); i++) {
                String tempName = tailNumbers.get(i); 
                int miles = 0;

                for (String[] value : map1.dataMap.values()) {
                    if(value[4].contentEquals(tempName) && value[19].contentEquals("0")) {
                        miles = miles + Integer.parseInt(value[21]);
                    }  
                }
                tailMiles.add(miles);     
            }

            Integer maxVal = Collections.max(tailMiles);
            Integer maxIdx = tailMiles.indexOf(maxVal);
            String maxPlane = tailNumbers.get(maxIdx);

            return maxPlane;
        }




        public HashMap<String,String[]> createHashMap() {
            File flightFile = new File("flights_small.csv");
            HashMap<String,String[]> flightsMap = new HashMap<String,String[]>();

            try {
            Scanner s = new Scanner(flightFile);
            while (s.hasNextLine()) {

                    String info = s.nextLine();
                    String [] piecesOfInfo = info.split(",");
                    String flightKey = piecesOfInfo[4] + "_" + piecesOfInfo[2] + "_" + piecesOfInfo[11]; //Setting the Key
                    String[] values = Arrays.copyOfRange(piecesOfInfo, 0, piecesOfInfo.length);

                    flightsMap.put(flightKey, values);

            }


            s.close();
            }


           catch (FileNotFoundException e)
           {
             System.out.println("Cannot open: " + flightFile);
           }

            return flightsMap;
        }
}
andrewjames:

La respuesta depende de lo que entendemos por "más eficiente", "terriblemente ineficiente" y "toma una eternidad". Estos son términos subjetivos. La respuesta también puede depender de factores técnicos específicos (consumo de memoria frente a la velocidad, el número de claves de vuelo únicas en comparación con el número de registros generales, etc.).

Yo recomendaría la aplicación de cierta racionalización básica a su código, para empezar. A ver si eso se consigue un mejor resultado (aceptable). Si necesita más, entonces se puede considerar mejoras más avanzadas.

Cualquier cosa que hagas, tomar algunas sincronizaciones para entender las amplias repercusiones de los cambios que realice.

Enfoque al pasar de "horrible" a "aceptable" - y luego preocuparse acerca de sintonía más avanzado después de eso (si todavía lo necesita).

Considere el uso de un BufferedReaderlugar de una Scanner. Ver aquí . A pesar de que el escáner puede estar muy bien para sus necesidades (es decir, si no es un cuello de botella).

Considere el uso de la lógica dentro de su bucle de escáner a los números de la cola de captura y el kilometraje acumulado en una sola pasada de los datos. El siguiente es deliberadamente básica, para mayor claridad y simplicidad:

// The string is a tail number.
// The integer holds the accumulated miles flown for that tail number:
Map<String, Integer> planeMileages = new HashMap();

if (planeMileages.containsKey(tailNumber)) {
    // add miles to existing total:
    int accumulatedMileage = planeMileages.get(tailNumber) + flightMileage;
    planeMileages.put(tailNumber, accumulatedMileage);
} else {
    // capture new tail number:
    planeMileages.put(tailNumber, flightMileage);
}

Después de eso, una vez que haya completado el bucle de escáner, puede iterar sobre el planeMileagesde encontrar el kilometraje más grande:

String maxMilesTailNumber;
int maxMiles = 0;
for (Map.Entry<String, Integer> entry : planeMileages.entrySet()) {
    int planeMiles = entry.getValue();
    if (planeMiles > maxMiles) {
        maxMilesTailNumber = entry.getKey();
        maxMiles = planeMiles;
    }
}

ADVERTENCIA - Este enfoque es sólo para ilustración. Sólo se capturará un número de cola. Podría haber múltiples planos con el mismo kilometraje máximo. Usted tendría que ajustar tu lógica para capturar múltiples "ganadores".

El enfoque anterior elimina la necesidad de que varios de sus estructuras de datos existentes, y relacionado con el procesamiento.

Si todavía se enfrentan a problemas, poner en algunos temporizadores para ver qué áreas de su código específico son más lento - y luego usted tendrá la oportunidad de sintonización más específicos se puede enfocar.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=284205&siteId=1
Recomendado
Clasificación