2017-04-19 4 views
0

私はメディアオブジェクトのリストを持っています。グループ化されたリストを並べ替えると、同じグループの要素が次々にJavaの中に現れないようになります。

Class structure of Media is : 
Integer id; 
String url; 
(@ManyToOne)EventEntity event,..etc 

Class structure of EventEntity is : 

Integer id; 
String name;....etc 

同じEventEntityの複数Mediaオブジェクトが存在する場合があります。 Mediaリストをランダムに並べ替えると、Media同じEventEntityのオブジェクトが次々に出現することはありません。例えば

、私の望ましい結果は次のとおりです。

[ 
{ 
"abc",event1 
}, 
{ 
"sdf",event2 
}, 
{ 
"sdf34",event1 
}, 
{ 
"sdsdafsdf",event3 
}, 
{ 
"sdf345f34",event2 
} 
] 

また、私は別のクラス - >Demo.class作成することができます。

Integer id; 
String url; 
Integer eventId; 

をそしてList<Demo>を移入し、ランダム化。 出力は次のようになります。

[ 
    { 
    5,"abc",1 
    }, 
    { 
    8,"sdf",2 
    }, 
    { 
    1,"sdf34",1 
    }, 
    { 
    2,"sdsdafsdf",3 
    }, 
    { 
    9,"sdf345f34",2 
    } 
    ] 

一部description.Java 8が好ましく、だけでなく、より効率的である方、旧バージョンであると示唆してください。

更新: List<Media>は、異なるEventEntityの要素数が異なる可能性があります。 たとえば、List<Media>には8つの要素があり、そのうちの5つは同じ要素を持ちます。EventEntity

この場合、ランダムな順序が実行されますが、ルールに従わない可能性がありますが、それに近づく必要があります。

+0

'List 'に5つの要素があり、そのうちの4つに同じ 'EventEntity'がある場合はどうなりますか? –

+0

@RobinTopper良い質問ですが、その場合は単純なランダム化が行われます。リストには、異なるイベントに対して同じ数のオブジェクトが含まれる場合と含まれない場合があります。 – SudeepShakya

+1

偶然性と構造的制約がスケールの反対側にあります。これらの矛盾する目標がどれだけ優先順位を持っているかを決めなければなりません。 – Holger

答えて

2

一つのアプローチは

List<Media> result = new ArrayList<>(mediaCollection.size()); 

ArrayList<Media> flatList = new ArrayList<>(mediaCollection); 
Map<Integer,Integer> countMap = new HashMap<>(); 
for(Media m: flatList) 
    countMap.merge(m.getEventEntity().getId(), 1, Integer::sum); 

Random r = ThreadLocalRandom.current(); 
Collections.shuffle(flatList, r); 

Integer previousID = null; 
while(!flatList.isEmpty()) { 
    for(int index = flatList.size()-1; index >= 0; index--) { 
     final Media m = flatList.get(index); 
     Integer id = m.getEventEntity().getId(); 
     if(previousID!=null && previousID.equals(id) && countMap.size()>1) continue; 
     previousID = id; 
     result.add(m); 
     flatList.remove(index); 
     countMap.merge(id, -1, (a,b) -> a==1? null: a+b); 
    } 
    if(countMap.size() == 1) { 
     result.addAll(flatList); 
     flatList.clear(); 
    } 
} 

このコピーflatListにすべての要素がそれらをシャッフルすることで、最終resultリストにコピーしながら、その後、以前と同じIDを有する要素は、次のコピー反復に延期されます(通常、最初のステップの後に残される要素はわずかです)。重要な部分は、同じIDを持つ要素だけが残っているときに停止することです。延期することはポイントがなく、無限ループにつながります。そのため、countMapが維持されています。各IDの数が追跡されますが、エントリはゼロになると削除されます。マップのサイズが1の場合、IDは1つだけ残され、残りの要素は一括して転送されます。

+0

返事ありがとうございます。効率について教えていただけますか? – SudeepShakya

+0

さて、 'Collections.shuffle'は、できるだけ効率的です。残りのコードのコストは無視できます。平均時間複雑度は 'O(n)'です。 – Holger

+0

私はあなたの提案を試みます、私は 'Collections.shuffle'も実装しました。 – SudeepShakya

関連する問題