Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

以下の条件のものを抽出 カウントする方法

お世話になります。

Java問題を探して、勉強しているものです。

2010-12-14 09:08をこっそりやっておりまして、
アドバイス頂けると助かります。

進捗状況としては、コレクションインターフェースのHashSetを利用して、以下のように記述致しました。
長くて申し訳ないですが、お時間が空いている時にでもご回答頂ければと思います。

import java.io.*;
import java.util.*;

class Test{
    public static void main(String args[]){
    
        BufferedReader br = null;
        
        try{
            br = new BufferedReader(new InputStreamReader(new FileInputStream("sample.txt")));
            
            String name = null;
            String engine = null;
            Set<Object> set = new HashSet<Object>();
            String[] array = null;
            String line;
            
            for(int i=0;(line=br.readLine())!=null;i++){
                array = line.split(",");
                name = array[0];
                engine = array[1];
                set.add(new Member(name,engine));
            }
            
            for(Object o : set){System.out.println(o);}
            
            //set = new TreeSet<Object>(set);
            //for(Object o : set){System.out.println(o);}
        }catch(FileNotFoundException e){e.printStackTrace();
        }catch(IOException e){e.printStackTrace();
        }finally{
            try{
                br.close();
            }catch(IOException e){e.printStackTrace();}
        }
    }
}

class Member implements Comparable{
    private String name;
    private String engine;
    public Member(String name,String engine){
        this.name = name;
        this.engine = engine;
    }
    public String getName(){return name;}
    public String getEngine(){return engine;}
    
    public String toString(){
        return "名前:" + name + "    機関:" + engine;
    }
    
    public boolean equals(Object obj){
        if((obj instanceof Member) && (name.equals(((Member)obj).getName()))){
            return true;
        }else{
            return false;
        }
    }
    
    public int hashCode(){
        return name.hashCode()+engine.hashCode();
    }
    
    public int compareTo(Object obj){
        return this.name.compareTo(((Member)obj).getName());
    }
}

実行結果は、以下のようになります。
名前:f  機関:鉄道
名前:c  機関:鉄道
名前:f  機関:バス
名前:e  機関:バス
名前:a  機関:自転車
名前:b  機関:バス
名前:b  機関:自転車
名前:a  機関:バス
名前:d  機関:自転車

欲しい結果としては、
名前:c  機関:鉄道
名前:d  機関:自転車
名前:e  機関:バス
となって欲しいのですが、for文の中に条件式を入れてうまく抽出できないでしょうか?

よろしくお願い致します。

29

回答

83576

閲覧

29件の回答

評価

0

まずは、その条件式とやらを、
ちょっとでも自分で書いてみましょうよ。

評価

0

一応、書いてみます。
※nameとengineはArrayListで管理するように変更しました。

            String temp = null;
            for(int i=0;(line=br.readLine())!=null;i++){
                array = line.split(",");
                name.add(array[0]);
                engine.add(array[1]);
                for(int j=0;true;j++){
                    if(name.get(i).equals(name.get(j))){
                        temp = name.get(i);
                    }else if(name.get(i).equals(temp)){
                        //処理しない
                    }else{
                        temp = name.get(i);
                    }
                    set.add(new Member(temp,engine.get(i)));
                    break;
                }
            }

実行した結果は、
名前:f  機関:鉄道
名前:c  機関:鉄道
名前:f  機関:バス
名前:e  機関:バス
名前:a  機関:自転車
名前:b  機関:バス
名前:b  機関:自転車
名前:a  機関:バス
名前:d  機関:自転車
と変わっていませんでした;;

良い条件式が思いつきません。
よろしくお願いします。

評価

0

逐次処理を行うためには、
データがあらかじめソートされている必要があるぞ。
ソートしてあったとしても、尻尾の処理が面倒だ。

まずは個人ごとに、どんな交通機関を使っているのか整理、集計して、
それから、一つしか使っていないかどうか、
判定するのがいいでしょう。

評価

0

アドバイス感謝です。
gg氏がやろうとしていた方法ですね。
それ以外でやれないか試していたのですが、面倒な処理をしなければならいのですか〜。
一度、集計して判定する方法でやってみようと思います。

評価

0

面白そうだったので私もやってみました。(Androidアプリだけど)
データは簡易的に2次元配列に固定で入れておき、Hashtable<String, List<String>>型の変数にデータを代入して作成しました。(データの整理)
Key=名前, Value=機関で使用しました。
あとはvalueのサイズが 1 のところを表示。(集計表示)

評価

0

Hashtableですか。
知らないので、調べて参考にさせて頂きます。
感謝致します。

評価

0

データが少ないようですね。Set 試したのなら Map も試してみませんか?
HashMap<String, HashSet<String>> を用意し、データーを全部入れる。
なお、マップやセットの種類は Hash... に限らず何でもかまわない。
もちろん名前をマップのキーにし、その名前に対する機関をセットに追加。
最後にマップ全体からセットのサイズが1の物を選ぶ。
セットの代わりに「1つしか使っていないかどうか」に特化した自前クラス
を使った方が簡単かもしれない。

評価

0

コレクションインターフェースのdocを見ていて、Mapの方がいいと思い、試しておりました!
いろいろな管理の仕方があって、どれがベスト(簡単)か迷いますが、とりあえず教えて頂いたもの全てやってみようと思います。

やりたい事はひとつですが、習熟の為いろいろ試してみようと思います。

評価

0

Map<名前, Map<交通機関, 回数>>とすると、いろいろ応用が利くかもね。

評価

0

進捗報告です。

まず、仙人氏の方法で試そうと思っております。
そこで質問なのですが、HashMap<String,HashSet<String>>で、mapのvalue箇所にHashSet<String>をセットされているのえすが、map.put()する場合にどのようにHashSetの要素をputしていけばいいかわかりません。
以下のようにして見たのですが、結果は鉄道と自転車しか表示されず、バスが上書きされておりました。


▼Test.java
Map<String,Object> map = new HashMap<String,Object>();
            HashSet<String> value = new HashSet<String>();
            String key = null;
            String line = null;
            String[] array = null;
            
            int bic_cnt = 0;
            int bus_cnt = 0;
            int rail_cnt = 0;
            
            for(int i=0;(line=br.readLine())!=null;i++){
                array = line.split(",");
                key = array[0];
                value.add(array[1]);
                for(Iterator iter = value.iterator();iter.hasNext();){
                    map.put(key,iter.next());
                }
            }
            
            Collection col = map.values();
            for(Object o : col){
                System.out.println(o);
            }

とりあえずは、Mapに入れたデータを出力するだけをやっています。
宜しくお願いします。

評価

0

MapのvalueがなんでObjectなんだろう。

それはともかく、MapでStringとHashSetをひもづけるんだから、Stringひとつに対してHashSetもひとつずつ用意しなきゃ。
今のだと全部同じHashSetじゃん。

評価

0

>MapのvalueがなんでObjectなんだろう。
HashSet<String>だとmap.put(key,value)の時に、どのようにvalueの要素を指定してあげるかわからなかったのです。Objectにしてれば、Iteratorでnext()すれば要素を順々にセットしていけると考えました。

>Stringひとつに対してHashSetもひとつずつ用意しなきゃ。
理解できないので、調べてみます。

アドバイス感謝いたします。

評価

0

>>Stringひとつに対してHashSetもひとつずつ用意しなきゃ。
>理解できないので、調べてみます。
>
多分調べても出ないと思うので...
Aさん、Bさん共に同じインスタンス(new HashSet<String>())を使用しているのでそれはダメと言うことでないかな。

評価

0

書き方はわからないですが、aさんが利用している交通機関の種類の合計、bさんが利用している交通機関の種類の合計・・・それらの合計の数が1になるものを名前+交通機関で表示する。

それをするには、同じインスタンスを使用しているとダメだよってことですね!!

一歩進んだ気がします。
がんばって調べてみます。

評価

0

>どのようにvalueの要素を指定してあげるかわからなかったのです。
素直に書けばいいはずだけど、試した上で言ってるのかな。
宣言はすでに提示してもらってるし。

Objectと書くのは、Genericsの利点を捨てることを意味するので、
Generics自体を使わないほうがマシかもね。
まあこの場合、キーはStringになってるけど。

評価

0

>素直に書けばいいはずだけど、試した上で言ってるのかな。
捻くれてるのかもしれないです。
一応、Map<String,HashSet<String>>で試したソースを貼り付けます。

▼Test.java
        for(int i=0;(line=br.readLine())!=null;i++){
            array = line.split(",");
            HashSet<String> set = new HashSet<String>();
            set.add(array[1]);
            map.put(array[0],set);
        }
        
        Set set = map.keySet();
        Iterator iter = set.iterator();
        while(iter.hasNext()){
            Object o1 = iter.next();
            Object o2 = map.get(o1);
            System.out.println(o1 + " : " + o2);
        }

▼実行結果
f : [バス]
d : [自転車]
e : [バス]
b : [バス]
c : [鉄道]
a : [バス]

と[]がつきます;;

評価

0

Objectは、具体的な型は
はっきりわかっているんだから、その通り書けばいい。
[]がつくのは、Collectionをそのまま表示しているから。

次は、HashSetのインスタンスを生成する前に、
mapにkeyが既にあるかどうかチェックするのに挑戦しては。

評価

0

Objectという型のことは、しばらく忘れた方がいい。
よく考えもせずに逃げてる。

#keySet()は、キーだけが必要なときに使うんだ。
キーと値、両方が欲しい場合は、#entrySet()を回す。
けっこうJavaに慣れた人でも、知らずに2010-12-17 17:37のような書き方をしてる人がいるけど。

評価

0

アドバイス感謝です。
逃げておりました。

keyの有無判定に挑戦してみます。
要素の取り出し方を調べていたところ、$氏がおっしゃっているように、entrySet()のやり方も記述されておりました。
ただ、用途別には書かれていませんでしたので、すごく勉強になります。
次回より、entrySet()で取り出すように致します。

ありがとう御座います!

評価

0

じゃあさらに書いておくと、Java5からは拡張for文を使って、iteratorを隠蔽してシンプルに書けるようになってる。
#entrySet()もこの恩恵に預かることができる。

評価

0

このスレ内部の話なのでここで質問させてもらってますが、別スレを立てた方がよい
のであれば言ってください。

$ さんの Map<名前, Map<交通機関, 回数>> (2010-12-16 11:24)に挑戦しているので
すが、わからないことがあるので教えてください。
宣言は「HashMap<String, HashMap<String, Integer>>」として回数部分をIntegerと
したのですが(intが使用できないため。)、交通機関が同じ場合に登録済みのInteger
型のオブジェクトを取得して「integerobj = integerobj.intValue()+1」とすると別
オブジェクトが生成されてしまいます。(Eclipseの変数ウィンドウのid値を参照。)
同一オブジェクトの値を書き換えるにはどうすればいいのでしょうか。

http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/Integer.html
を見てみたのですが、値を書き換えるようなメソッドは用意されていないようです。
この場合、intラッパークラスを自分で用意すればできますが、他にも方法があるの
でしょうか。
通常は別オブジェクトになっても気にせずに使用するものでしょうか。
またはIntegerではなく他の型を使用するのでしょうか。

評価

0

そういう場合は、新しい値をputすることで、valueを上書きします。

ラッパークラスは、俺なら使わないな。

評価

0

ちょっと的外れか。

>同一オブジェクトの値を書き換えるにはどうすればいいのでしょうか。

こういう場合は、「同一オブジェクト」には、
こだわらないってことね。
もちろん、こだわる自由もある。

評価

0

うん、別にMapとかIntegerとか、ある時点で提示されたものにこだわる必要なんかなくて、例えばそれ専用のBeanを作ってもいいわけだ。
そうやって1つの完成形に満足せず、いろいろ考えたり他の人の意見を聞いたりしてどんどんコードを変えていくのが、力を付けることになると思ってる。
状況に応じた「良さそうな形」を、最初から思いつけるようになる。

業務では、一回作ったものを根本的に変えることはなかなかできないからね。
趣味でやってるんだから、どう修正しようと自由。
そういうことをやっておけば、業務でも最初から「良さそうな形」を出せるようになる。

評価

0

不良社員 さん、$ さん回答ありがとうございます。
今はAndroidアプリをやっているのでどうするのがメモリ、速度のバランスが良いの
か、またはJAVAでのセオリーみたいのがあるのか気になって投稿しました。

>1つの完成形に満足せず、いろいろ考えたり他の人の意見を聞いたりしてどんどん
>コードを変えていくのが、力を付けることになると思ってる。
>
にははげしく同意。
ただ、周りでJAVAやってる人がいないから掲示板とかでないと意見を聞いたりでき
ないのが難点ですが。

評価

0

それこそネットの時代なんだから、別に「周り」にこだわる必要がない。

評価

0

>> GOD
プリミティブ型のラッパークラス及びStringのオブジェク
トは、immutable  objectといって生成された時点で状態
が確定し、その後の変更はできません。
ちょっと昔、「文字列連結は +演算子を使用せず
StringBufferを使え」と盛んに言われていた時期がありま
したが、それはStringがimmutable(不変)であるためで
す。
(今だとStringBuilderのほうが良いかもしれません)

たとえば、String s = "abc" + "def"; というコードを書
いた場合、VM上では、"abc"、"def"、"abcdef"の3つのオ
ブジェクトが作成されることになります。
"abc"、"def"はテンポラリ・オブジェクトなので即GC対象
になりますが。

昨今のサーバ/PC上で動くアプリであれば、そこまでリ
ソースを気にすることも無いと思いますが、Androidとい
うことですので、Googleが公表しているパフォーマンス・
ガイドラインなども参照されることをお奨めします。
http://developer.android.com/intl/ja/guide/practices
/design/performance.html

確か翻訳されている方が居られたと思いますので、探せば
翻訳版が見つかるかもしれません。

評価

0

細かいけど

String s1 = "abc";
String s2 = "def";
String s = s1 + s2;

じゃないと3つのオブジェクトにならないんじゃないかな。
静的な足し算はコンパイラが処理してしまう。

s1とs2が他に使われてなければ、こう書いても最適化で消えるかもしれない。

評価

0

A さん回答ありがとうございます。
Integer 型に値を書き換えるメソッドが用意されていない理由がわかりました。
イミュータブルオブジェクトと呼ばれるものだったんですね。耳慣れない言葉だっ
たのでwikiで調べて納得できました。

Googleが公表しているパフォーマンス・ガイドラインは翻訳版ですが一読済みです。
(日本語部は。英語部は翻訳機に入れて単語拾いながらなんとかなので怪しいですがw)
http://www.techdoctranslator.com/android/practices/performance
ここを読んでいたので「オブジェクトの生成は避ける」が気になり、どうなんだろう
という疑問に発展した次第です。

Android の場合、「メモリ、速度のバランス」を考慮するとミュータブルオブジェク
トとして自作の int ラッパークラスを自分で作成するのがいいのかな?可読性は非
常に落ちそうですが。
可読性を考慮すると不良社員さんのおっしゃるようにオブジェクト生成されても気に
しないで作成かな。生成量と場面に応じて切り替えて使用していかないと...

※ 勝手ながら「2010-12-21 16:39」の件ついての回答は締めさせてください。これ以上回答をいただくとJavaQさんのスレを乗っ取ってしまいそうなのでm(_._)m

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。