sort array java php jsp tomcat

array - collections.sort java



Matrices de matrices en Java (11)

Esto es desagradable para mí ... Soy un tipo PHP que trabaja en Java en un proyecto JSP. Sé cómo hacer lo que intento con demasiados códigos y una completa falta de delicadeza.

Prefiero hacerlo bien. Aquí está la situación:

Estoy escribiendo una pequeña pantalla para mostrar a los clientes qué días pueden regar sus céspedes en función de su grupo de riego (ABCDE) y en qué época del año es. Nuestras estaciones se ven así: Verano (5-1 a 8-31) Primavera (3-1 a 4-30) Caída (9-1 a 10-31) Invierno (11-1 a 2-28)

Un ejemplo podría ser:

Si estoy en el grupo A, aquí estaré mi tiempo permitido: Invierno: solo los lunes. Primavera: martes, jueves y sábados. Verano: cualquier día de otoño: martes, jueves y sábados.

Si estuviera escribiendo esto en PHP, usaría matrices como esta:

//M=Monday,t=Tuesday,T=Thursday.... etc $schedule["A"]["Winter"]=''M''; $schedule["A"]["Spring"]=''tTS''; $schedule["A"]["Summer"]=''Any''; $schedule["A"]["Fall"]=''tTS''; $schedule["B"]["Winter"]=''t'';

PODRÍA hacer los arreglos de días (matriz ("Martes", "Jueves", "Sábado")), etc., pero no es necesario para lo que realmente estoy tratando de lograr.

También necesitaré configurar arreglos para determinar en qué temporada estoy:

$seasons["Summer"]["start"]=0501; $seasons["Summer"]["end"]=0801;

¿Alguien puede sugerir una forma genial de hacer esto? Tendré la fecha de hoy y la carta del grupo. Tendré que salir de mi función un día (M) o una serie de días (tTS), (Cualquiera).


No hay una solución bonita. Java simplemente no hace cosas como esta bien. La solución de Mike es más o menos la forma de hacerlo si quieres cadenas como los índices (claves). Otra opción si la configuración de hash-of-hashes es demasiado fea es unir las cadenas (desvergonzadamente robadas de Mike y modificadas):

Hashtable<String, String> schedule = new Hashtable<String, String>(); schedule.put("A-Winter", "M"); schedule.put("A-Spring", "tTS");

y luego búsqueda:

String val = schedule.get(group + "-" + season);

Si no está satisfecho con la fealdad general (y no lo culpo), ponga todo detrás de una llamada a un método:

String whenCanIWater(String group, Date date) { /* ugliness here */ }


No soy un programador de Java, pero alejándome de Java y pensando en términos que son más independientes del idioma, una forma más clara de hacerlo podría ser utilizar constantes o tipos enumerados. Esto debería funcionar en cualquier lengua que admita matrices multidimensionales.

Si usa constantes con nombre, donde, por ejemplo:

int A = 0; int B = 1; int C = 2; int D = 3; int Spring = 0; int Summer = 1; int Winter = 2; int Fall = 3; ...

Entonces las constantes sirven como subíndices de matriz más legibles:

schedule[A][Winter]="M"; schedule[A][Spring]="tTS"; schedule[A][Summer]="Any"; schedule[A][Fall]="tTS"; schedule[B][Winter]="t";

Usando tipos enumerados:

enum groups { A = 0, B = 1, C = 2, D = 3 } enum seasons { Spring = 0, Summer = 1, Fall = 2, Winter = 3 } ... schedule[groups.A][seasons.Winter]="M"; schedule[groups.A][seasons.Spring]="tTS"; schedule[groups.A][seasons.Summer]="Any"; schedule[groups.A][seasons.Fall]="tTS"; schedule[groups.B][seasons.Winter]="t";


Podría hacer esencialmente el mismo código con Hashtables (o algún otro mapa):

Hashtable<String, Hashtable<String, String>> schedule = new Hashtable<String, Hashtable<String, String>>(); schedule.put("A", new Hashtable<String, String>()); schedule.put("B", new Hashtable<String, String>()); schedule.put("C", new Hashtable<String, String>()); schedule.put("D", new Hashtable<String, String>()); schedule.put("E", new Hashtable<String, String>()); schedule.get("A").put("Winter", "M"); schedule.get("A").put("Spring", "tTS"); // Etc...

No es tan elegante, pero, una vez más, Java no es un lenguaje dinámico, y no tiene valores hash en el nivel de idioma.

Nota: Es posible que pueda hacer una mejor solución, esto simplemente apareció en mi cabeza cuando leí su pregunta.


¿La "fecha" tiene que ser un parámetro? Si solo muestra el programa de riego actual, la clase WateringSchedule puede determinar qué día es y, por lo tanto, en qué temporada es. Luego solo tiene un método que devuelve un mapa donde la clave es la letra del grupo. Algo como:

public Map<String,List<String>> getGroupToScheduledDaysMap() { // instantiate a date or whatever to decide what Map to return }

Luego en la página JSP

<c:forEach var="day" items="${scheduler.groupToScheduledDaysMap["A"]}"> ${day} </c:forEach>

Si necesita mostrar los horarios durante más de una temporada, debe tener un método en la clase WateringSchedule que devuelva un mapa donde Seasons son las claves, y luego Maps of groupToScheduledDays son los valores.


Esta es una forma en que podría verse, puedes descifrar el resto:

A = new Group(); A.getSeason(Seasons.WINTER).addDay(Days.MONDAY); A.getSeason(Seasons.SPRING).addDay(Days.TUESDAY).addDay(Days.THURSDAY); A.getSeason(Seasons.SPRING).addDays(Days.MONDAY, Days.TUESDAY, ...); schedule = new Schedule(); schedule.addWateringGroup( A );


Estoy con aquellos que sugieren encapsular la función en los objetos.

import java.util.Date; import java.util.Map; import java.util.Set; public class Group { private String groupName; private Map<Season, Set<Day>> schedule; public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public Map<Season, Set<Day>> getSchedule() { return schedule; } public void setSchedule(Map<Season, Set<Day>> schedule) { this.schedule = schedule; } public String getScheduleFor(Date date) { Season now = Season.getSeason(date); Set<Day> days = schedule.get(now); return Day.getDaysForDisplay(days); } }

EDITAR: Además, los intervalos de fechas no tienen en cuenta los años bisiestos:

Nuestras estaciones se ven así: Verano (5-1 a 8-31) Primavera (3-1 a 4-30) Caída (9-1 a 10-31) Invierno (11-1 a 2-28)


Estoy de acuerdo en que definitivamente debes poner esta lógica detrás de la interfaz limpia de:

public String lookupDays(String group, String date);

pero tal vez deberías pegar los datos en un archivo de propiedades. No estoy en contra de la codificación de estos datos en sus archivos fuente, pero como ha notado, Java puede ser muy prolijo cuando se trata de colecciones anidadas. Su archivo puede verse así:

A.Summer = M
A.Spring = tTS
B.Summer = T

Por lo general, no me gusta mover datos estáticos como este a un archivo externo porque aumenta la "distancia" entre los datos y el código que lo usa. Sin embargo, cada vez que se trata de colecciones anidadas, especialmente mapas, las cosas pueden ponerse realmente feas, muy rápido.

Si no te gusta esta idea, tal vez puedas hacer algo como esto:

public class WaterScheduler { private static final Map<String, String> GROUP2SEASON = new HashMap<String, String>(); static { addEntry("A", "Summer", "M"); addEntry("A", "Spring", "tTS"); addEntry("B", "Summer", "T"); } private static void addEntry(String group, String season, String value) { GROUP2SEASON.put(group + "." + season, value); } }

Pierdes algo de legibilidad, pero al menos los datos están más cerca de donde se usarán.


No entiendo por qué algunos de ustedes parecen pensar que arrojar cantidades de objetos al código es el camino a seguir. Por ejemplo, hay exactamente cuatro estaciones, y no hacen ni almacenan nada. ¿Cómo simplifica algo para convertirlos en objetos? Wing tiene razón en que estas deberían ser constantes (o tal vez enumeraciones).

Lo que Bruce necesita, en su corazón, es simplemente una tabla de búsqueda. Él no necesita una jerarquía de objetos e interfaces; él necesita una manera de buscar un horario basado en una temporada y un identificador de grupo. Convertir las cosas en objetos solo tiene sentido si tienen responsabilidades o estado. Si no tienen ninguno, entonces son simplemente identificadores, y la creación de objetos especiales para ellos solo hace que la base de código sea más grande.

Podría compilar, por ejemplo, objetos Group que contengan un conjunto de cadenas de programación (uno para cada temporada), pero si todo el objeto Group hace es proporcionar funcionalidad de búsqueda, entonces habrá reinventado la tabla de búsqueda de una manera mucho menos intuitiva. Si tiene que buscar el grupo y luego buscar el programa, todo lo que tiene es una tabla de búsqueda de dos pasos que tardó más en codificarse, es más probable que tenga errores y será más difícil de mantener.


No intentes ser tan dinámico como PHP. Podría intentar definir primero lo que necesita.

interface Season { public string getDays(); } interface User { public Season getWinter(); public Season getSpring(); public Season getSummer(); public Season getFall(); } interface UserMap { public User getUser(string name); }

Y por favor, lea la documentación de Hashtable antes de usarlo. Esta clase está sincronizada, lo que significa que cada llamada está protegida contra multihilo, lo que realmente ralentiza el acceso cuando no se necesita protección adicional. Utilice cualquier implementación de Map en su lugar como HashMap o TreeMap .


Parece que todo el mundo está intentando encontrar la forma Java de hacerlo como si lo estuvieras haciendo en PHP, en lugar de hacerlo de la forma en que debería hacerse en Java. Simplemente considere cada pieza de su matriz un objeto o, como mínimo, el primer nivel de la matriz como un objeto y cada subnivel como variables dentro del objeto. Construya una estructura de datos que llene con dichos objetos y acceda a los objetos a través de los accesores proporcionados por la estructura de datos.

Algo como:

class Schedule { private String group; private String season; private String rundays; public Schedule() { this.group = null; this.season = null; this.rundays= null; } public void setGroup(String g) { this.group = g; } public String getGroup() { return this.group; } ... } public ArrayList<Schedule> schedules = new ArrayList<Schedule>(); Schedule s = new Schedule(); s.setGroup(...); ... schedules.add(s); ...

Por supuesto que probablemente tampoco sea correcto. Haría que cada temporada sea un objeto, y quizás cada lista de días laborables como un objeto también. De todos modos, es más fácilmente reutilizable, entendido y extensible que un Hashtable cojo que intenta imitar tu código PHP. Por supuesto, PHP también tiene objetos, y debe usarlos de manera similar en lugar de sus matrices uber, siempre que sea posible. Aunque entiendo la tentación de hacer trampa. ¡PHP lo hace tan fácil y divertido!


Una mejor solución sería, tal vez, poner todos esos datos en una base de datos, en lugar de codificarla en sus fuentes o usar archivos de propiedades.

Usar una base de datos será mucho más fácil de mantener, y hay una variedad de motores de base de datos gratuitos para elegir.

Dos de estos motores de base de datos se implementan completamente en Java y se pueden incrustar en una aplicación simplemente al incluir un archivo jar. Es un poco pesado, claro, pero es mucho más escalable y fácil de mantener. El hecho de que haya 20 registros hoy no significa que no habrá más tarde debido a los requisitos cambiantes o al deslizamiento de características.

Si, en unas pocas semanas o meses, decide que desea agregar, por ejemplo, restricciones de riego de la hora del día, será mucho más fácil agregar esa funcionalidad si ya está usando una base de datos. Incluso si eso nunca sucede, entonces has pasado unas horas aprendiendo cómo insertar una base de datos en una aplicación.