É o seguinte eu tenho um programa que compara o conteúdo das linhas do excel e depois conteúdo das colunas. O problema é que se o arquivo for muito grande ele demora muito (mais de 15 minutos), o que eu posso fazer pra deixar mais rápido? Eu tentei usar Sortedmap, mas ele muda a ordem e retira algumas linhas. Alguém poderia me ajudar?
Você pode continuar a usar um SortedMap mesmo, mas em vez de você ter um SortedMap <Integer, String> (por exemplo), você pode usar um SortedMap <Integer, List>
Mas era assim que eu estava usando
Isa, queria saber mais ou menos qual era a sua lógica para demorar tanto. Por que é que você precisa do número da linha, para começar?
O primeiro passo para corrigir a demora de um software, é descobrir o que demora.
Para isso, use um profiler, como esse que vem no Java:
http://visualvm.java.net/
O JVisualVM está na pasta bin do JDK. Aí basta otimizar o ponto que estiver encrencado.
Estou chutando que você queira fazer algo como o seguinte:
Dado o arquivo
+---+-------+
| | A |
+---+-------+
| 1 | joao |
| 2 | joao |
| 3 | maria |
| 4 | jose |
| 5 | joao |
| 6 | maria |
+---+-------+
você quer gerar um arquivo assim (nesta ordem):
joao - 1, 2, 5
maria - 3, 6
jose - 4
É isso?
[quote=entanglement]Estou chutando que você queira fazer algo como o seguinte:
Dado o arquivo
+---+-------+
| | A |
+---+-------+
| 1 | joao |
| 2 | joao |
| 3 | maria |
| 4 | jose |
| 5 | joao |
| 6 | maria |
+---+-------+
você quer gerar um arquivo assim (nesta ordem):
joao - 1, 2, 5
maria - 3, 6
jose - 4
É isso?[/quote]
É por ai, onde os nomes se repetem eu vou procurar em determinada coluna da linha para ver se os nomes são iguais, eu também vejo se as colunas forem iguais mesmo as linhas com os nomes sendo diferentes.
Eu sei o que o deixa lento, ele compara linha por linha no documento (e mais de uma vez). Só que geralmente vem mais de mil linhas, alias mil linhas é o mínimo. Não sei como melhora-lo. Como já disse tentei sortedmap, ele faz bem mais rápido, mas ele tira algumas linhas e também mudar a sua ordem.
Então você provavelmente terá de fazer um outro mapa, que faz com que seja mais rápido comparar nomes.
Seria um LinkedHashMap <String, List> onde a chave é o nome, e Linha é uma classe que representa os campos úteis de uma linha dessa planilha (contendo os diversos campos que você deseja comparar, incluindo o nome completo, o número da linha, etc.)
Note que o LinkedHashMap preserva a ordem das strings que estão nesse HashMap.
A idéia é primeiramente preencher esse LinkedHashMap, e depois você verificar se cada List tem mais de um elemento (pelo que imagino, você está querendo remover as informações duplicadas ou inconsistentes, não)? Se cada List tem mais de um elemento, você pode então aplicar as verificações necessárias.
Isso deve ser muito, muito mais rápido que o que você está fazendo (comparando cada linha com cada linha, pelo que imagino - ou seja, se sua planilha tem 1000 linhas, você faria 1000000 de comparações, o que é insano).
[quote=entanglement]A idéia é primeiramente preencher esse LinkedHashMap, e depois você verificar se cada List tem mais de um elemento (pelo que imagino, você está querendo remover as informações duplicadas ou inconsistentes, não)? Se cada List tem mais de um elemento, você pode então aplicar as verificações necessárias.
Isso deve ser muito, muito mais rápido que o que você está fazendo (comparando cada linha com cada linha, pelo que imagino - ou seja, se sua planilha tem 1000 linhas, você faria 1000000 de comparações, o que é insano). [/quote]
Não eu não quero remove-las eu preciso delas, tudo que estiver na planilha não pode sair dela e nem mudar de posição. O que eu tenho que fazer é se os valores de duas (ou mais linhas, mas nesse caso os valores das colunas não são iguais) linhas forem iguais e uma determinada coluna de uma das linhas tiver o mesmo valor de outra coluna na outra linha igual eu pinto a célula do excel. Eu não posso tirar os iguais e as posições não pode mudar. Como disse antes eu conseguir deixar mais rapido com sortedmap, mas com ele as posições das linhas mudam e a perca de dados. Mesmo as linhas diferentes tem que permanecer no arquivo, nada pode se perde.
Ah, entendi. Você só quer pintar as células que estão discrepantes (ou seja, criar um novo arquivo que tem os mesmos dados, mas comentados).
Pois bem, o LinkedHashMap pode ser usado porque ele não muda posições relativas das chaves.
[quote=entanglement]Ah, entendi. Você só quer pintar as células que estão discrepantes (ou seja, criar um novo arquivo que tem os mesmos dados, mas comentados).
Pois bem, o LinkedHashMap pode ser usado porque ele não muda posições relativas das chaves.
[/quote]
Ta certo, vou olhar para ver se funciona.
A minha duvida agora é outra, como eu faço para comparar? Eu tentei só substituir no código sortedmap por LinkedHashMap (e mesmo assim houve algumas auteraçẽs na ordem das linhas, mas acho que foi por causa da forma que estou comparando), mas da forma que estou comparando há perca de informação, então como faço para comparar usando LinkHashMap sem perde informações? Tipo eu primeiro comparo as linhas para depois comparar as colunas, mas tem linhas que não tem o que eu quero comparar elas seriam como um cabeçalho e não podem ser retiradas.
Veja se esta implementação de MultiKeyMap é mais rápida para você. Ela não destrói o map original, mas as entradas são as mesmas do map original, modificar uma modifica a mesma no multikeymap.
[code]import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MultiKeyMap<K, V> {
private Map<V, List<Entry<K, V>>> innerMap = new LinkedHashMap<V, List<Entry<K, V>>>();
public MultiKeyMap(Map<K, V> map) {
LinkedHashMap<K, V> backup = new LinkedHashMap<K, V>(map);
if (backup.size() > 0) {
do {
Iterator<Entry<K, V>> it = backup.entrySet().iterator();
Entry<K, V> firstEntry = it.next();
V value = firstEntry.getValue();
List<Entry<K, V>> entryList = new LinkedList<Entry<K, V>>();
entryList.add(firstEntry);
innerMap.put(value, entryList);
it.remove();
if (value == null) {
while (it.hasNext()) {
Entry<K, V> entry = it.next();
if (entry.getValue() == null) {
entryList.add(entry);
it.remove();
}
}
} else {
while (it.hasNext()) {
Entry<K, V> entry = it.next();
if (value.equals(entry.getValue())) {
entryList.add(entry);
it.remove();
}
}
}
} while (backup.size() > 0);
}
}
public Set<Entry<V, List<Entry<K, V>>>> entrySet() {
return innerMap.entrySet();
}
}
[/code]
[code]import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class TestMultiKeyMap {
public static void main(String[] args) {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("A1", "joao");
map.put("A2", "joao");
map.put("A3", "maria");
map.put("A13", null);
map.put("A4", "jose");
map.put("A5", "joao");
map.put("A6", "maria");
map.put("A14", null);
MultiKeyMap<String, String> multiKeyMap = new MultiKeyMap<String, String>(map);
for (Iterator<Entry<String, List<Entry<String, String>>>> it = multiKeyMap.entrySet().iterator(); it.hasNext();) {
Entry<String, List<Entry<String, String>>> entry = it.next();
System.out.println(entry.getKey());
for (Entry<String, String> value : entry.getValue()) {
System.out.println("\t" + value.getKey());
}
}
System.out.println(map);
}
}
[/code]
[quote=Bruno Laturner]Veja se esta implementação de MultiKeyMap é mais rápida para você. Ela não destrói o map original, mas as entradas são as mesmas do map original, modificar uma modifica a mesma no multikeymap.
[code]import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MultiKeyMap<K, V> {
private Map<V, List<Entry<K, V>>> innerMap = new LinkedHashMap<V, List<Entry<K, V>>>();
public MultiKeyMap(Map<K, V> map) {
LinkedHashMap<K, V> backup = new LinkedHashMap<K, V>(map);
if (backup.size() > 0) {
do {
Iterator<Entry<K, V>> it = backup.entrySet().iterator();
Entry<K, V> firstEntry = it.next();
V value = firstEntry.getValue();
List<Entry<K, V>> entryList = new LinkedList<Entry<K, V>>();
entryList.add(firstEntry);
innerMap.put(value, entryList);
it.remove();
if (value == null) {
while (it.hasNext()) {
Entry<K, V> entry = it.next();
if (entry.getValue() == null) {
entryList.add(entry);
it.remove();
}
}
} else {
while (it.hasNext()) {
Entry<K, V> entry = it.next();
if (value.equals(entry.getValue())) {
entryList.add(entry);
it.remove();
}
}
}
} while (backup.size() > 0);
}
}
public Set<Entry<V, List<Entry<K, V>>>> entrySet() {
return innerMap.entrySet();
}
}
[/code]
[code]import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class TestMultiKeyMap {
public static void main(String[] args) {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("A1", "joao");
map.put("A2", "joao");
map.put("A3", "maria");
map.put("A13", null);
map.put("A4", "jose");
map.put("A5", "joao");
map.put("A6", "maria");
map.put("A14", null);
MultiKeyMap<String, String> multiKeyMap = new MultiKeyMap<String, String>(map);
for (Iterator<Entry<String, List<Entry<String, String>>>> it = multiKeyMap.entrySet().iterator(); it.hasNext();) {
Entry<String, List<Entry<String, String>>> entry = it.next();
System.out.println(entry.getKey());
for (Entry<String, String> value : entry.getValue()) {
System.out.println("\t" + value.getKey());
}
}
System.out.println(map);
}
}
[/code][/quote]
Você poderei explicar esse código, por favor?