17

これは私にとって厄介なことです...私はJSPプロジェクトでJavaで作業している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';

日の配列 (array("Tuesday","Thursday","Saturday")) などを作成できますが、実際に達成しようとしていることには必要ありません。

また、現在の季節を判断するために配列をセットアップする必要があります。

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

誰かがこれを行うための本当にクールな方法を提案できますか? 今日の日付とグループレターを持ってきます。私は、1 日 (M) または一連の日数 (tTS) (任意) で、自分の機能を終了する必要があります。

4

12 に答える 12

11

ハッシュテーブル(または他のマップ)を使用して、基本的に同じコードを実行できます。

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は動的言語ではなく、言語レベルでのハッシュもありません。

注:あなたはより良い解決策を実行できるかもしれません、これは私があなたの質問を読んだときに私の頭に浮かんだだけです。

于 2008-08-15T23:16:52.383 に答える
9

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を使用する前に、ドキュメントをお読みください。このクラスは同期されます。つまり、追加の保護が必要ない場合は、各呼び出しがマルチスレッドから保護され、アクセスが実際に遅くなります。代わりに、 HashMapTreeMapなどのMap実装を使用してください。

于 2008-08-16T00:21:05.763 に答える
6

誰もが、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コードを模倣しようとする、まとまりのないハッシュテーブルよりも簡単に再利用、理解、拡張できます。もちろん、PHPにもオブジェクトがあります。可能な限り、uber-arrayの代わりに同様の方法でオブジェクトを使用する必要があります。しかし、私はカンニングの誘惑を理解しています。PHPはそれをとても簡単で、とても楽しいものにします!

于 2008-08-16T00:28:34.220 に答える
4

これがそのように見える1つの方法です、あなたは残りを理解することができます:

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 );
于 2008-08-16T07:37:11.967 に答える
3

私は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";
于 2008-08-15T23:56:20.010 に答える
2

コードにオブジェクトの塊を投げるのが道だと考える人がいるように思われる理由について、私は完全に途方に暮れています。たとえば、ちょうど4つの季節があり、何もしません、何も保存しません。それらをオブジェクトにするために、どのように単純化するのですか?ウィングは、これらがおそらく定数(またはおそらく列挙型)であるべきだということは非常に正しいです。

ブルースが必要としているのは、本質的には単なるルックアップテーブルです。彼はオブジェクトとインターフェースの階層を必要としません。彼は季節とグループ識別子に基づいてスケジュールを検索する方法を必要としています。物事をオブジェクトに変えることは、それらが責任または状態を持っている場合にのみ意味があります。どちらも持っていない場合、それらは単なる識別子であり、それらのために特別なオブジェクトを構築すると、コードベースが大きくなります。

たとえば、それぞれが一連のスケジュール文字列(季節ごとに1つ)を含むオブジェクトを作成できますが、オブジェクトがルックアップ機能を提供するだけの場合は、はるかに直感的でない方法でルックアップテーブルを再発明しました。彼がグループを検索してからスケジュールを検索する必要がある場合、彼が持っているのは2段階のルックアップテーブルだけで、コーディングに時間がかかり、バグが多く、保守が困難になります。GroupGroup

于 2008-08-16T01:07:35.577 に答える
2

私は、オブジェクトに関数をカプセル化することを提案するものと一緒です。

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);
    }

}

編集:また、日付範囲はうるう年を考慮していません:

私たちの季節は次のようになります:夏(5-1から8-31)春(3-1から4-30)秋(9-1から10-31)冬(11-1から2-28)

于 2008-08-16T12:04:54.377 に答える
1

より良い解決策は、ソースにハードコーディングしたり、プロパティファイルを使用したりするのではなく、すべてのデータをデータベースに配置することです。

データベースを使用すると、保守がはるかに簡単になり、さまざまな 無料の データベース エンジンから選択できます。

これらのデータベースエンジンのうち2つは、完全にJavaで実装されており、jarファイルを含めるだけでアプリケーションに埋め込むことができます。確かに少し重いですが、はるかにスケーラブルで保守が簡単です。今日20のレコードがあるからといって、要件の変更や機能のクリープのためにそれ以上のレコードがなくなるわけではありません。

数週間または数か月以内に、たとえば時間帯の散水制限を追加することにした場合、すでにデータベースを使用している場合は、その機能を追加する方がはるかに簡単です。それが決して起こらないとしても、あなたはデータベースをアプリケーションに埋め込む方法を学ぶのに数時間を費やしました。

于 2008-08-16T01:46:37.243 に答える
1

私はあなたが間違いなくこのロジックを次のクリーンなインターフェースの背後に置くべきであることに同意します:

public String lookupDays(String group, String date);

ただし、データをプロパティファイルに貼り付ける必要があるかもしれません。私はこのデータをソースファイルにハードコーディングすることに反対していませんが、お気づきのように、ネストされたコレクションに関しては、Javaはかなり言葉になります。ファイルは次のようになります。

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

通常、このような静的データを外部ファイルに移動するのは好きではありません。これは、データとそれを使用するコードとの間の「距離」が長くなるためです。ただし、ネストされたコレクション、特にマップを扱う場合は常に、物事が非常に醜く、非常に速くなる可能性があります。

このアイデアが気に入らない場合は、次のようなことができます。

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);
  }

}

読みやすさは失われますが、少なくともデータは使用される場所に近くなります。

于 2008-08-16T00:53:11.563 に答える
1

「日付」はパラメータである必要がありますか?現在の散水スケジュールを表示しているだけの場合、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のマップが値であるマップを返すメソッドが必要です。

于 2008-08-16T04:35:49.557 に答える
0

きれいな解決策はありません。Javaはこのようなことをうまく行いません。インデックス(キー)として文字列が必要な場合、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 */ }
于 2008-08-15T23:27:13.673 に答える