質問
現在、インターネットテクノロジーは成熟しており、ますます分散化され、分散型、ストリームコンピューティングがあり、Java側のデータベース側で行われた多くのことを置いています。今日、データベースフィールドにインデックスがない場合、フィールドに基づいてどのように重複する必要があるかと尋ねました。誰もがJavaを使用してそれを行うことに同意しますが、それを行う方法は?
答え
突然、私は前に重い重い重量を削除するためにリストに書いた記事を思い出し、それを見つけて読んだ。この方法は、ハッシュコードを書き換え、リスト内のオブジェクトのメソッドに等しく、ハッシュセットに投げてから取り出すことです。これは、Javaを最初に学んだときに辞書のように書き留めた答えです。たとえば、インタビューの場合、Javaに3年間滞在している人は、SetとHashmapの違いを記憶できますが、実装方法がわかりません。言い換えれば、初心者は特性を暗記するだけです。しかし、プロジェクトで実際にそれを使用している場合、それが真実であることを確認する必要があります。承認は役に立たないため、結果を信じることができます。ハッシュセットが私が重い体重を取り除くのにどのように役立つかを知る必要があります。考えてみると、ハッシュセットなしで重い負荷を削除できますか?最も単純で最も直接的な方法は、毎回履歴データと比較し、異なる場合はキューの尾に挿入することです。ハッシュセットはこのプロセスをスピードアップします。
まず、オブジェクトユーザーにソートを提供します
@data@builder@allargsconstructorpublic classユーザー{private integer id; private string name;} list <user> users = lists.newarraylist(new user(1、 "a")、new user(1、 "b")、new user(2、 "b")、new user(1、 "a"));目標は、重複したIDのないユーザーを取り出すことです。口論を防ぐために、私はルールを与えます。独自のIDを使用してデータを自由に取得するだけで、IDが同じ場合に計算されるものについて誠実である必要はありません。
最も直感的な方法を使用します
この方法は、空のリストを使用して、トラバースデータを保存することです。
@testpublic void dis1(){list <user> result = new linkedlist <>(); for(user user:user){boolean b = result.stream()。anymatch(u-> u.getid()。equals(user.getid()); if(!b){result.add(user); }} system.out.println(result);}ハッシュセットを使用します
機能を覚えている人は誰でも、ハッシュセットが重い重量を除去できることを知っているので、重いウェイトを除去するにはどうすればよいですか?ハッシュコードに従って、それをもう少し深く覚え、メソッドに等しくなります。では、これら2つに基づいてどのように基づいていますか?ソースコードを読んでいない人は継続することができず、インタビューはここで終了します。
実際、ハッシュセットはハッシュマップによって実装されています(ソースコードを見たことがなく、ハッシュメップのキーはハッシュセットによって実装されると常に直感的に考えていました。これはまったく逆です)。ここで説明を拡張することはありません。構築方法を見て、理解するためのハッシュセットの方法を追加してください。
public hashset(){map = new hashmap <>();}/***明らかに、それが存在する場合、それはfalseを返します、それが存在しない場合、それはtrue*/public boolean add(e e){return map.put(e、present)== null;}次に、これからハッシュセットの繰り返しがハッシュマップに基づいて実装されており、ハッシュマップの実装はハッシュコードに完全に依存し、メソッドに等しいことがわかります。今では完全に開かれています。ハッシュセットを使用したい場合は、2つの方法について楽観的でなければなりません。
この質問では、IDに基づいて推定する必要があるため、比較ベースはIDです。変更は次のとおりです。
@overridepublic boolean equals(object o){if(this == o){return true; } if(o == null || getClass()!= o.getClass()){return false; } user user =(user)o; return objects.equals(id、user.id);}@overridepublic int hashcode(){return objects.hash(id);} // hashcoderesult = 31 * result +(element == null?0:element.hashcode());その中でも、オブジェクトはアレイのハッシュコードを呼び出し、コンテンツは上記のようです。 x << 5-xに等しい31を掛けます。
最終的な実装は次のとおりです。
@testpublic void dis2(){set <user> result = new Hashset <>(users); System.out.println(result);}Javaストリームを使用して重複排除します
最初の質問に戻ると、この質問をする理由は、データベース側をJava側に再び再び調整する場合、100,000個などのデータの量が比較的大きい場合があるためです。ビッグデータの場合、ストリーム関連の関数を使用することが最も簡単です。ストリームが明確な関数も提供するように。では、どのように使用する必要がありますか?
users.parallelStream()。個別()。foreach(system.out :: println);
ラムダはパラメーターとして見ていませんでした。つまり、カスタム条件は提供されていません。幸いなことに、Javadocは重複排除基準をマークしました。
このストリームの個別の要素(@linkオブジェクト#equals(object)}に従って)で構成されるストリームを返します。
また、この原則を記憶しなければならないことを知っています。等しい場合、returnが真である場合、ハッシュコードの返品値は同じでなければなりません。これは、記憶するときは少し論理的に混乱しますが、ハッシュマップの実装方法を理解している限り、話すのは難しいとは感じません。 HashMapは最初にHashCodeメソッドに従って見つけ、次にEqualsメソッドを比較します。
したがって、個別を使用して重複排除を実現するには、デフォルトのものを使用しない限り、ハッシュコードと等しいメソッドをオーバーライドする必要があります。
それで、なぜあなたはこれをするのですか?クリックして、実装をご覧ください。
<p_in> node <t> reduce(pipelinehelper <t> helper、spliterator <p_in> spliterator){//ストリームがソートされている場合は、次のように並べ替える必要があります// linkedhashset :: add、linkedhashset :: addall); nodes.nodeを返す(decop.p.evaluate parallel(helper、splitterator));}内部実装は、削減することで実現されます。 Reduceについて考えるとき、あなたは即座にDistingByKeyを自分で実装する方法を考えます。 reduceを使用する必要があります。計算部分は、ストリーム要素を組み込みのハッシュマップと比較し、ある場合はスキップし、noがある場合はそれらを入力することです。実際、このアイデアは、最初は最も簡単な方法です。
@testpublic void dis3(){users.parallelstream()。filter(disticebykey(user :: getId))。 return t-> see.add(keyextractor.apply(t));}もちろん、それが平行なストリームである場合、取られるストリームは必ずしも最初のストリームではなく、ランダムです。
上記の方法は最適であり、非侵襲的です。ただし、個別を使用する必要がある場合。ハッシュコードのみを書き換えることができ、ハッシュセットメソッドのように等しくなります。
まとめ
これらのものを自分で使用できるかどうかのみ練習することができます。そうでなければ、本当にそれらを使用したいときにそれらを一度に取り出すことは困難です。さもないと、リスクがあります。そして、本当に大胆に使用したい場合は、ルールと実装の原則を理解する必要もあります。たとえば、LinkedHashsetとHashsetの実装はどのように異なりますか?
単純なLinkedHashsetソースコードに添付されています。
パブリッククラスのLinkedHashset <e>拡張ハッシュセット<e>実装<e> set <e>、cloneable、java.io.serializable {private static final long serialversionuid = -28516676799971038690l; public linkedhashset(int initialcapacity、float loadfactor){super(initialcapacity、loadfactor、true); } public linkedhashset(int initialcapacity){super(initialcapacity、.75f、true); } public linkedhashset(){super(16、.75f、true); } public linkedhashset(collection <?extends e> c){super(math.max(2*c.size()、11)、.75f、true); addall(c); } @Override public Spliterator <e> spliterator(){return spliterators.spliterator(this、spliterator.distinct | spliterator.ORDERED); }}補充:
Javaのリストコレクションから重複データを削除する方法
1.リスト内のすべての要素をループしてから、複製を削除します
public static list removeduplicate(list list){for(int i = 0; i <list.size() - 1; i ++){for(int j = list.size() - 1; j> i; j-){if(list.get(j).equals(list.get(i))){list.remove(j); }}} return list; } 2。ハッシュセットを介して重複要素をキックオフします
public static list remodeveduplicate(list list){hashset h = new Hashset(list); list.clear(); list.addall(h);返品リスト。 }3. ArrayListの重複要素を削除して、注文を維持します
// arrayListで複製要素を削除するには、public static void remodeduplicatewithorder(list list){set set = new Hashset();リストnewList = new ArrayList(); for(iterator iter = list.iterator(); iter.hasnext();){object element = iter.next(); if(set.add(element))newlist.add(element); } list.clear(); list.addall(newlist); system.out.println( "Demof Duplicate" + list); }4。リスト内のオブジェクトを反復し、list.contain()を使用し、存在しない場合は別のリストコレクションに入れます。
public static list remodeveduplicate(list list){list listtemp = new ArrayList(); for(int i = 0; i <list.size(); i ++){if(!listtemp.contains(list.get(i))){listtemp.add(list.get(i)); }} return listtemp; }