2017-03-01 5 views
0

私は学校の問題に取り組んでいます。このメソッドの多くは既に実装されており、あまりにも多くの変更を加えることはできません。消費者外のリストを変更するには

実際には私はスポットに変更することしかできません。

私が取り組んでいるメソッドのコードですが、いくつかの単語はオランダ語で書かれています。

ファイルの行を読み込み、テキストからアドレスを作成し(street + "+ number +" "+ place)として保存されます)、返されたリストに追加します。ファイルは空の行で終了します。

@Override 
public List<Adres> query(ISpecification specification) { 
    if (specification instanceof FileSpecification) { 
     if (((FileSpecification) specification).toFileQuery().equals("ALL")) { 
      ArrayList<Adres> adressen = new ArrayList<>(); 
/*---start of my code*/ 
      File studentF = new File(fsConnection.getStudentConnection()); 
      try { 
       FileReader fr = new FileReader(studentF); 
       BufferedReader br = new BufferedReader(fr); 
       br.lines().forEach(new Consumer<String>(){ 
        @Override 
        public void accept(String line) { 
         String[] words = line.split("\\s"); 
         if(words.length == 3){ 
/*line i'm having trouble with*/adressen.add(new Adres(words[0], Integer.parseInt(words[1]), words[2]); 
         } 
        } 
       }); 
      } catch (FileNotFoundException ex) { 
       Logger.getLogger(AdresFile.class.getName()).log(Level.SEVERE, null, ex);//Don't mind this 
      } 
/*---end of my code*/ 
      //System.out.println("query: Nog niet geimplementeerd!"); 
      return adressen; 
     } else { 
      return null; 
     } 
    } else { 
     return null; 
    } 
} 

ご覧のとおり、コンシューマーブロックの外にあるリストにアクセスしたいと思っていました。私は今これが不可能であることを知っています。私は別の方法を作成することを考えましたが、それは許されません。私はforeachメソッドを使用する必要があります。どんな助けもありがとうございます。あなたはJava7で作業しているとき

+0

はリスト 'final'を作ってみます: 'final ArrayList adressen =新しいArrayList <>();'。 – Berger

+0

しかし、リストを変更できないようにしていませんか? – Typhaon

+0

いいえ、後で他のオブジェクトを 'adressen'変数に割り当てることができないことを意味します。 – Berger

答えて

2

、コンパイラが

final ArrayList<Adres> adressen = new ArrayList<>(); 

が必要になります。ポイントは、ローカル変数内に使用したいと思います。言い換えれば、ソースコードを入れたクラスから何らかの形で切り離されたコンテキストでは、そして、デカップリングされたクラスのためにを使用する adressenは最終的である必要があります(コンパイラーが知っているので、後でその参照は変更されません)。そして、あなたのコメントが与えられました:いいえ、これは魔法のようにオブジェクトを不変に変えません。 参照が、それが指している「ターゲット」を変更するのを防ぐだけです!

しかし、あなたはその行を変更することが許可されていないとして、あなたが行くことができる:

ArrayList<Adres> adressen = new ArrayList<>(); 
final ArrayList<Adres> tempAdressen = adressen; 

、その後あなたコード使用tempAdressenを持っています。

また、Java7を使用していると仮定します。 Java8の場合、コンパイラはadressenであることを理解できるはずです。;したがって、ソースコードをそのまま受け入れるべきです。

+0

私はJava 8がそれを認識できることを知りませんでした。さて、良い習慣は既にここにありますが、知っておいてよかったです。 – AxelH

+0

あなたは大歓迎です;-) – GhostCat

0

BufferedReaderのlines()を呼び出すため、すでにJava8を使用しているようです。

私の提案は、forEachの代わりにマップを作成してリストを作成することです。この方法では、消費者のリストからアクセスする必要はありません。 Java8で

adressen.addAll(
    br.lines().map(line -> { 
        String[] words = line.split("\\s"); 
        if (words.length == 3) { 
         return new Adres(words[0], Integer.parseInt(words[1]), words[2]); 
        } 
        return null; 
       }) 
      .filter(Objects::nonNull) 
      .collect(Collectors.toList()) 
); 
0

、あなたは、ストリームから直接、要素のリストを返すためにjava.util.stream.Collectorsを使用することができます。コレクタの使用は、副作用を避けるのに役立ちます(あなたの場合、要素を解析するために外部配列を使用する必要があります)。

私は個人的には、以下のラムダを使用してそれを記述します。

List<Adres> adressen = br.lines().stream() 
    .map(line -> line.split("\\s")) 
    .filter(words -> words.length == 3) 
    .map(words -> new Adres(words[0], Integer.parseInt(words[1]), words[2])) 
    .collect(Collectors.toList()); 

これは動作しますが、まだそれはデータが不正である場合を処理しません。その問題を解決するために、1行がラムダを変更することで、3つの要素で構成されていない場合に処理するために、上記のコードを変更することができます(これは非常にエレガントでない場合でも):

List<Adres> adressen = br.lines().stream() 
    .map(line -> line.split("\\s")) 
    .filter(words -> { 
     if (words.length == 3) 
      return true; 
     else { 
      throw new IllegalArgumentException(); 
     } 
    }) 
    .map(words -> new Adres(words[0], Integer.parseInt(words[1]), words[2])) 
    .collect(Collectors.toList()); 
関連する問題