2014-09-11 6 views
1

Я столкнулся с проблемой производительности в своем коде на Java. Я должен подсчитывать частоту каждого объекта, созданного процессом. Тип объекта - «Узел», приведенный ниже. В настоящее время я решил эту проблему, используя технику типа HashMap, приведенную ниже в test1. Однако этот процесс очень медленный, потому что мое моделирование генерирует 100 миллионов миллионов объектов. Более того, я должен разбить String во время каждой итерации, а затем повторить конкатенацию и так далее. Поэтому я подумывал применить технику так, как показано ниже в test2. Но HashMap рассматривает каждый новый объект как новую запись независимо от содержимого внутри объекта. Мне интересно, если кто-то знает, как эффективно решить эту проблему.Ошибка производительности в Java

public class NewMain { 

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    // TODO code application logic here 
     String[] a={"c","d"}; 
     int[] b={1,2}; 

    Map<String, Integer> test1=new HashMap<>(); 
    test1.put(new Node(a, b).toString(), 1); 
    test1.put(new Node(a, b).toString(), 3); 
    System.out.println(test1.size()); // size is 1 

     ////////////////////////// 
     Map<Node, Integer> test2=new HashMap<>(); 
     test2.put(new Node(a, b), 1); 
     test2.put(new Node(a, b), 3); 
     System.out.println(test2.size()); // size is 2 

} 
} 
    class Node{ 
    String[] a; 
    int[] b; 

public Node(String[] a, int[] b) { 
    this.a = a; 
    this.b = b; 
} 
public String toString(){ 
String result=null; 
    for(String e:a) 
     result+=e+"|"; 
    for(int e:b) 
     result+=e+"|"; 
    return result; 
} 

} 
+3

Override 'hashCode' для вашего класса' Node'? –

+3

@ C.B. и 'equals' – resueman

+0

любой конкретной причиной, по которой вы используете' String', а не 'Node' в качестве ключа? – Amadan

ответ

0

Попробуйте это в вашем Node классе:

@Override 
public int hashCode() { 
    int result = 1; 
    for(String e:a) 
     result = result * 31 + e.hashCode(); 
    for(int e:b) 
     result = result * 31 + e; 
    return result; 
} 

@Override 
public boolean equals(Object obj) { 
    return this.hashCode() == obj.hashCode(); 
} 

Это говорит Java, что нужно сравнивать объекты путем сравнения их хеш-кодов - по умолчанию только для сравнения указателей, и гарантирует, что хэш-код рассчитанный на основе содержимого класса. Это даст вам результат 1 для вашего звонка test2.size().


Или, на основе @ bjlee72-х внушения выше, Eclipse дает мне:

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + Arrays.hashCode(a); 
    result = prime * result + Arrays.hashCode(b); 
    return result; 
} 
@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    Node other = (Node) obj; 
    if (!Arrays.equals(a, other.a)) 
     return false; 
    if (!Arrays.equals(b, other.b)) 
     return false; 
    return true; 
} 
+0

Отлично! просто быстрый вопрос. Я хочу использовать только строковый массив «a». Поэтому я удалил второй цикл в hashCode(). Но будет ли проблема избежать даже первого цикла и просто использовать public int hashCode() {return a.hasCode();}. Это дает правильный результат, хотя, но мне интересно, будет ли какое-либо столкновение для большого количества содержимого. – user3212493

+0

Теперь вы указываете на это, мой код «equals» действительно запускает риск столкновений, но версия Eclipse этого не делает. Угадав при реализации «Карты», он может сначала сделать «hashCode» для быстрого сравнения, а затем «равно», чтобы проверить, является ли это просто столкновением или фактическим совпадением. Пожалуйста, выберите версию Eclipse поверх моей, так как она будет более надежной. –

Смежные вопросы