Java中的数组数组
对我来说这是一个讨厌的人...我是一个在Java上从事JSP项目的PHP专家。我知道如何通过过多的代码和完全缺乏技巧来做我要尝试的事情。
我宁愿做对。情况如下:
我正在写一个小显示器,以根据客户的浇水组(ABCDE)向客户展示他们可以在几天浇水,以及一年中的什么时间。我们的季节如下所示:
夏季(5-1至8-31)
春季(3-1至4-30)
下降(9-1至10-31)
冬季(11-1至2-28)
一个示例可能是:
如果我在A组中,这将是我的允许时间:
冬季:仅星期一
春季:周二,周四,周六
夏季:任何一天
秋季:周二,周四,周六
如果我是用PHP编写的,则将使用如下数组:
//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';
我可以制作days数组(array(" Tuesday"," Thursday"," Saturday"))等,但是对于我真正想要完成的事情,这不是必需的。
我还需要设置数组以确定我所在的季节:
$seasons["Summer"]["start"]=0501; $seasons["Summer"]["end"]=0801;
谁能建议一种非常酷的方法来做到这一点?我要有今天的日期和团体信。我将需要一天(M)或者一系列天(tTS),(任何)退出我的功能。
解决方案
回答
我们可以使用Hashtables(或者其他一些Map)执行基本上相同的代码:
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...
不那么优雅,但是再说一次,Java不是动态语言,并且在语言级别没有哈希值。
注意:我们也许可以做一个更好的解决方案,当我阅读问题时,这个解决方案突然出现在我的脑海中。
回答
没有很好的解决方案。 Java只是做得不好。如果我们想将字符串用作索引(键),则Mike的解决方案几乎就是该方法。如果哈希的设置太丑陋,另一个选择是将字符串添加在一起(从Mike偷偷偷偷修改):
Hashtable<String, String> schedule = new Hashtable<String, String>(); schedule.put("A-Winter", "M"); schedule.put("A-Spring", "tTS");
然后查找:
String val = schedule.get(group + "-" + season);
如果我们对一般的丑陋不满意(我不怪我们),请将其全部放在方法调用后面:
String whenCanIWater(String group, Date date) { /* ugliness here */ }
回答
我不是Java程序员,而是摆脱了Java的束缚,只是想着一些与语言不可知的术语,这是一种更干净的方法,它可能是使用常量还是枚举类型。这应该在支持多维数组的任何语言中都有效。
如果使用命名常量,例如:
int A = 0; int B = 1; int C = 2; int D = 3; int Spring = 0; int Summer = 1; int Winter = 2; int Fall = 3; ...
然后,常量用作更易读的数组下标:
schedule[A][Winter]="M"; schedule[A][Spring]="tTS"; schedule[A][Summer]="Any"; schedule[A][Fall]="tTS"; schedule[B][Winter]="t";
使用枚举类型:
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";
回答
不要尝试像PHP一样动态。我们可以尝试首先定义所需的内容。
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); }
并且,请在使用前阅读Hashtable的文档。此类是同步的,这意味着每个调用都受到保护,免受多线程攻击,这在我们不需要额外保护时会真正减慢访问速度。请改用任何Map实现,例如HashMap或者TreeMap。
回答
似乎每个人都在尝试找到Java的实现方式,就像在PHP中那样,而不是在Java中应采用的方式。只需将数组的每个部分视为一个对象,或者至少将数组的第一级视为一个对象,并将每个子级视为该对象内部的变量。构建一个数据结构,我们可以用上述对象填充该数据结构,并通过数据结构的给定访问器访问这些对象。
就像是:
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); ...
当然那也不对。我将每个季节作为对象,也许每个工作日也将其作为对象。无论如何,它比试图模仿PHP代码的笨拙的Hashtable更容易重用,理解和扩展。当然,PHP也有对象,我们应该尽可能以类似的方式使用它们,而不是使用超级数组。我确实理解作弊的诱惑。 PHP使它变得如此简单和有趣!
回答
我同意,我们绝对应该将此逻辑放在以下干净接口的后面:
public String lookupDays(String group, String date);
但是也许我们应该将数据粘贴到属性文件中。我不反对在源文件中对这些数据进行硬编码,但是,正如我们所注意到的,当涉及到嵌套集合时,Java可能会非常罗y。文件可能看起来像:
A.Summer=M A.Spring=tTS B.Summer=T
通常,我不喜欢将这样的静态数据移动到外部文件,因为它会增加数据与使用它的代码之间的"距离"。但是,每当我们处理嵌套的Collection(尤其是地图)时,事情都会变得非常丑陋,快速。
如果我们不喜欢这个主意,也许我们可以做这样的事情:
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); } }
我们失去了一些可读性,但至少数据更接近将要使用的位置。
回答
我完全茫然不知为什么有些人似乎认为将对象的对象扔到代码上是必经之路。例如,恰好有四个季节,它们不做任何事情或者存储任何东西。如何简化使它们成为对象的任何事物? Wing说的很对,这些应该应该是常量(或者可能是枚举)。
本质上,布鲁斯需要的只是一个查询表。他不需要对象和接口的层次结构。他需要一种基于季节和组标识符查找时间表的方法。将事物变成对象只有在他们有责任或者有状态时才有意义。如果它们都没有,那么它们只是标识符,为它们构建特殊的对象只会使代码库变大。
例如,我们可以构建Group'对象,每个对象都包含一组时间表字符串(每个季节一个),但是如果所有
Group`对象所做的只是提供查找功能,那么我们已经在很多方面重新构造了查找表不太直观的时尚。如果他必须先查找组,然后再查找时间表,那么他所拥有的只是一个两步查找表,该表花了更长的时间编写代码,更有可能是儿童车,而且很难维护。
回答
更好的解决方案可能是将所有数据放入数据库中,而不是在源中或者使用属性文件对其进行硬编码。
使用数据库将易于维护,并且有多种免费的数据库引擎可供选择。
这些数据库引擎中的两个完全用Java实现,只需包含jar文件就可以将它们嵌入到应用程序中。当然,这有点重量级,但是它具有更大的可伸缩性和易于维护的功能。仅仅因为今天有20条记录,并不意味着以后由于需求的变化或者功能变化而不会再有更多的记录。
如果我们在几周或者几个月内决定要添加一天中的浇水限制,那么如果我们已经在使用数据库,则添加该功能会容易得多。即使从未发生过,我们也已经花了几个小时学习如何在应用程序中嵌入数据库。
回答
是否必须将"日期"作为参数?如果我们只是显示当前的浇水时间表,WateringSchedule类本身可以确定是哪一天,因此是什么季节。然后只有一个方法可以返回映射,其中Key是组字母。就像是:
public Map<String,List<String>> getGroupToScheduledDaysMap() { // instantiate a date or whatever to decide what Map to return }
然后在JSP页面
<c:forEach var="day" items="${scheduler.groupToScheduledDaysMap["A"]}"> ${day} </c:forEach>
如果需要显示多个季节的时间表,则WateringSchedule类中应该有一个方法,该方法返回一个以Seasons为键,然后以groupToScheduledDays的Maps为值的地图。
回答
这是一种可能的样子,我们可以弄清楚其余部分:
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 );
回答
我与那些建议在对象中封装功能的人在一起。
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); } }
编辑:此外,日期范围不考虑leap年:
Our seasons look like this: Summer (5-1 to 8-31) Spring (3-1 to 4-30) Fall (9-1 to 10-31) Winter (11-1 to 2-28)