pergunta
Atualmente, a tecnologia da Internet é madura e, mais e mais, tende a ser descentralizada, distribuída e de computação de fluxo, que colocou muitas coisas que foram feitas no lado do banco de dados no lado Java. Hoje alguém perguntou, se o campo do banco de dados não tem índice, como deve ser desduplicado com base no campo? Todo mundo concorda em usar o Java para fazê -lo, mas como fazê -lo?
responder
De repente, lembrei -me do artigo que escrevi na lista para remover pesos pesados antes e o encontrei e o li. O método é reescrever os métodos HashCode e é igual ao objeto na lista, jogá -lo no hashset e retirá -lo. Esta é a resposta que escrevi como um dicionário quando aprendi Java pela primeira vez. Por exemplo, ao entrevistar, as pessoas que estão em Java há 3 anos, podem memorizar a diferença entre o Set e o Hashmap, mas não sabem como implementá -lo. Em outras palavras, os iniciantes apenas memorizam as características. Mas quando você está usando -o em um projeto, precisa garantir que seja verdade. Como o endosso é inútil, só posso acreditar no resultado. Você precisa saber como o hashset pode me ajudar a me livrar da carga pesada. Se você pensar bem, pode remover a carga pesada sem hashset? A maneira mais simples e direta é compará -lo com dados históricos sempre e inseri -los na cauda da fila, se for diferente. E o hashset apenas acelera esse processo.
Primeiro, dê ao usuário do objeto para classificar
@Data@builder@alargsconstructorpublic classe usuário {private integer id; Nome da String Private;} Lista <suser> usuários = lists.newArrayList (novo usuário (1, "A"), novo usuário (1, "B"), novo usuário (2, "B"), novo usuário (1, "A"));O objetivo é retirar o usuário sem ID duplicado. Para evitar brigas, dou uma regra. Basta retirar dados com IDs exclusivos à vontade e não precisa ser consciente sobre qual é calculado quando o ID é o mesmo.
Use o método mais intuitivo
Este método é usar uma lista vazia para armazenar os dados percorridos.
@Testpublic void Dis1 () {list <suser> resultado = new LinkedList <> (); para (usuário do usuário: usuários) {boolean b = resultado.stream (). anymatch (u -> u.getId (). igual (user.getId ())); if (! b) {resultado.add (usuário); }} System.out.println (resultado);}Use hashset
Quem memorizou os recursos sabe que o hashset pode remover pesos pesados, então como faço para remover pesos pesados? Memorize um pouco mais profundo e de acordo com os métodos HashCode e é igual a. Então, como isso é baseado nesses dois? As pessoas que não leram o código -fonte não podem continuar e a entrevista termina aqui.
De fato, o hashset é implementado pelo Hashmap (nunca vi o código -fonte e sempre pensei intuitivamente que a chave do hashmap é implementada pelo Hashset, que é exatamente o oposto). Não vou expandir a descrição aqui, basta olhar para o método de construção e adicionar o método de hashset para entender.
public hashSet () {map = new Hashmap <> ();}/*** Obviamente, se existir, retornará false, se não existir, retorna verdadeiro*/public boolean add (e e) {retorno map.put (e, presente) == null;}Em seguida, também pode ser visto a partir disso que a repetição do hashset é implementada com base no hashmap, e a implementação do hashmap depende completamente dos métodos HashCode e é igual. Agora está completamente aberto. Se você deseja usar o hashset, deve estar otimista sobre seus dois métodos.
Nesta pergunta, precisamos deduzir com base no ID, portanto, nossa base de comparação é ID. As modificações são as seguintes:
@OverridePublic boolean é igual (objeto o) {if (this == O) {return true; } if (o == null || getClass ()! = O.getClass ()) {return false; } Usuário usuário = (usuário) o; retornar objetos.equals (id, user.id);}@substituirpublic int hashcode () {return Objects.hash (id);} // hashcodeResult = 31 * resultado + (element == null? 0: element.hashcode ());Entre eles, os objetos chamam o HashCode de Matriz e o conteúdo é mostrado acima. Multiplique por 31 é igual a x << 5-x.
A implementação final é a seguinte:
@Testpublic void dis2 () {set <suser> resultado = novo hashset <> (usuários); System.out.println (resultado);}Use o fluxo Java para desduplicar
Voltando à pergunta inicial, o motivo para fazer essa pergunta é que, se você deseja obter novamente o lado do banco de dados do lado Java, a quantidade de dados pode ser relativamente grande, como 100.000 peças. Para big data, o uso de funções relacionadas a fluxos é a mais fácil. Assim como o fluxo também fornece a função distinta. Então, como deve ser usado?
users.paralLelsTream ().
Não vi Lambda como um parâmetro, ou seja, nenhuma condição personalizada foi fornecida. Felizmente, Javadoc marcou o padrão de desduplicação:
Retorna um fluxo que consiste nos elementos distintos (de acordo com {@link objeto#equals (objeto)}) deste fluxo.Sabemos que também devemos memorizar esse princípio: quando iguais retorna true, o valor de retorno do HashCode deve ser o mesmo. Isso é um pouco confuso logicamente ao memorizar, mas enquanto entendemos o método de implementação do Hashmap, não nos sentiremos difíceis de conversar. O hashmap primeiro localiza de acordo com o método HashCode e, em seguida, compara o método igual.
Portanto, para usar distintos para obter desduplicação, você deve substituir os métodos HashCode e equivale a menos que use o padrão.
Então, por que você faz isso? Clique e dê uma olhada na implementação.
<p_in> nó <T> Reduce (tubulação <t> helper, spliterator <p_in> spliterator) {// Se o fluxo for classificado, ele também deve ser solicitado para que o seguinte também // preserve o término de classificação: link <t, linkhashset <T>> Reduced = ReducedOps. LinkedHashSet :: Add, LinkedHashSet :: addall); Retornar nós.Node (ReduDOP.Evaluateparallelal (ajudante, Splitterator));}O interno é implementado usando redução. Quando você pensa em reduzir, pensa instantaneamente em um método para implementar o DistinctbyKey sozinho. Eu só preciso usar o Reduce, e a parte do cálculo é comparar os elementos do fluxo com um hashmap embutido, pule-os se houver e colocá-los se houver. De fato, a idéia é o método mais direto no início.
@Testpublic void Dis3 () {users.paralLelsTream (). Filtro (distinctbyKey (user :: getId)) .ForEach (System.out :: println);} public static <t> predicado <t> distinthKey (function <? Super TE,? retornar t -> ver.add (keyextractor.apply (t));}Obviamente, se for um fluxo paralelo, o que é levado não é necessariamente o primeiro, mas é aleatório.
O método acima é o melhor encontrado e não invasivo. Mas se você tiver que usar distinto. Você só pode reescrever o código de hash e é igual ao método de hashset.
resumo
Você só pode praticar se você pode usar essas coisas você mesmo. Caso contrário, será difícil tirá -los de uma só vez, quando você realmente deseja usá -los, ou você corre o risco. E se você realmente deseja usá -lo com ousadia, também é necessário entender as regras e os princípios de implementação. Por exemplo, como as implementações do LinkedHashSet e Hashset são diferentes?
Anexado com o código fonte simples do LinkedHashSet:
Classe pública LinkedHashSet <E> estende o hashset <e> implementos conjunto <e>, clonável, java.io.serializável {private estático final serialversionuid = -2851667679971038690L; 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 (coleção <? 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); }}Reabastecer:
Método para remover dados duplicados da coleção de listas em java
1. Loop todos os elementos na lista e depois exclua duplicatas
Lista estática pública Removeduplicate (lista de lista) {for (int i = 0; i <list.size () - 1; i ++) {for (int j = list.size () - 1; j> i; j -) {if (list.get.get (j) .equals (list.get (i))) {list.roMove (j); }}} Lista de retorno; } 2. Inicie os elementos duplicados através do hashset
Lista estática pública Removeduplicate (lista de lista) {hashset h = new HashSet (lista); list.clear (); list.addall (h); lista de retorno; }3. Exclua elementos duplicados no ArrayList para manter a ordem
// Exclua elementos duplicados no ArrayList, mantenha a ordem do vazio estático público removido RemovedUplicateWither (lista de lista) {set set = new HashSet (); List newList = new ArrayList (); for (iterator iter = list.iterator (); iter.hasnext ();) {objeto elemento = iter.next (); if (set.add (element)) newList.add (elemento); } list.clear (); list.addall (newlist); System.out.println ("Remover Duplicate" + List); }4. Itera sobre o objeto na lista, use list.contain () e, se não existir, coloque -o em outra coleção de listas.
Lista estática pública Removeduplicate (lista de lista) {list listTemp = new ArrayList (); for (int i = 0; i <list.size (); i ++) {if (! listTemp.Contains (list.get (i))) {listTemp.add (list.get (i)); }} retornar listTemp; }