有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java提高了自动建议算法的效率和速度

在我的项目中,为了插入一个自动建议函数(也存在一些插入错误,如Google),我创建了以下类:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Searcher {

private ArrayList<String> titoli;
private boolean multiThread;
private int numeroCore;
private Thread [] threads;
private int indice;
private String [] testoSplittato;
private SortedSet<String> risultati;
private final Runnable runnable;

public Searcher (ArrayList<String> titoli , boolean multiThread) {
    this.titoli = titoli;
    this.multiThread = multiThread;
    indice = 0;
    risultati = new TreeSet<String> ();
    numeroCore = multiThread ? Runtime.getRuntime().availableProcessors() : 1;
    threads = new Thread [numeroCore];
    runnable = new Runnable () {
        @Override
        public void run () {                    
            String prossimo;
            while ((prossimo = getProssimo ()) != null) {
                if (suggerimentoDaAggiungere (prossimo.toLowerCase()))
                    aggiungiRisultato (prossimo);
            }
        }
    };
    for (int i=0;i<threads.length;i++) {
        threads [i] = new Thread (runnable);
    }
}

public Searcher (ArrayList<String> titoli) {
    this (titoli, false);
}

private synchronized void setIndice (int n) {
    indice = n;
}

private synchronized String getProssimo () {
    try {
        return titoli.get(indice++);
    }catch (IndexOutOfBoundsException ioobe) {
        return null;
    }
}

public synchronized void aggiungiRisultato (String s) {
    risultati.add(s);
}

private boolean mancaUnaLettera (String a , String b) {
    int al = a.length() , bl = b.length();
    if (al < 2 || al >= bl)
        return false;

    //a più corta di b
    int primaLetteraSbagliata = -1;
    for (int i=0;i<al;i++) {
        if (a.charAt (i) != b.charAt(i)) {
            primaLetteraSbagliata = i;
            break;
        }
    }

    return primaLetteraSbagliata >= 0 && (b.substring(0, primaLetteraSbagliata) + b.substring(primaLetteraSbagliata + 1)).indexOf(a) >= 0;
}

private boolean unaLetteraDiTroppo (String a , String b) {
    int al = a.length() , bl = b.length();
    if (al < 3 || al - 1 > bl)
        return false;

    //a più corta o stessa lunghezza di b
    int primaLetteraSbagliata = -1;
    for (int i=0;i<bl;i++) {
        if (a.charAt(i) != b.charAt(i)) {
            primaLetteraSbagliata = i;
            break;
        }
    }

    //non sono sicurissimo di qui
    if (primaLetteraSbagliata == -1 && al + 1 == bl)
        return true;

    return primaLetteraSbagliata >= 0 && b.indexOf ((primaLetteraSbagliata > 0 ? a.substring(0 , primaLetteraSbagliata) : "") + (primaLetteraSbagliata + 1 < al ? a.substring(primaLetteraSbagliata + 1) : "") ) >= 0;
}

private boolean unaLetteraSbagliata (String a , String b) {
    int al = a.length() , bl = b.length();
    if (al < 3 || al > bl)
        return false;

    //a ha lunghezza >= di b
    int primaLetteraSbagliata = -1;
    for (int i=0;i<al;i++) {
        if (a.charAt(i) != b.charAt(i)) {
            primaLetteraSbagliata = i;
            break;
        }
    }

    boolean ok = primaLetteraSbagliata + 1 < al;

    return primaLetteraSbagliata >= 0 && (b.substring(0, primaLetteraSbagliata) + (ok ? b.substring(primaLetteraSbagliata + 1) : "")).indexOf(a.substring(0, primaLetteraSbagliata) + (ok ? a.substring(primaLetteraSbagliata + 1) : "")) >= 0;
}

private boolean presenteConErrore (String chiave , String titolo) {
    String [] titoloSplittato = titolo.split(" ");
    if (titolo.indexOf (chiave) >= 0)
        return true;
    for (String s : titoloSplittato)
        if (mancaUnaLettera (chiave , s) || unaLetteraDiTroppo (chiave, s) || unaLetteraSbagliata (chiave, s))
            return true;

    return false;
}

public boolean suggerimentoDaAggiungere (String titolo) {        
    for (String s : testoSplittato) {
        if (!presenteConErrore (s,titolo))
            return false;
    }

    return true;
}

public SortedSet<String> getSuggerimenti (String testo) {
    for (Thread t : threads) {
        if (/*t != null && */t.isAlive()) {
            t.interrupt();
        }
    }
    testoSplittato = testo.toLowerCase ().split (" ");
    risultati.clear();
    if (testoSplittato.length > 0) {
        setIndice (0);
        for (int i=0;i<threads.length;i++) {
            threads [i] = new Thread (runnable);
            threads [i].setPriority(Thread.MAX_PRIORITY);
            threads [i].start();
        }
    }
    for (Thread t : threads)
        try {
            t.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(Searcher.class.getName()).log(Level.SEVERE, null, ex);
        }
    //System.out.println ("FINITO");

    return risultati;                              
}

public static ArrayList<String> getTitoli (String titleFilePath) {
    ArrayList<String> restituire = new ArrayList<String> ();
    try {
        BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream (titleFilePath) {}));
        String s;
        while ((s = br.readLine ()) != null) {
            restituire.add (s);
        }
    } catch (Exception ex) {
        Logger.getLogger(Searcher.class.getName()).log(Level.SEVERE, null, ex);
    }

    return restituire;
}

}

对你来说,有可能提高这个算法的效率和速度吗?如果是,怎么可能? 另外,我知道exist为这些函数(比如Lucene)提供了专门的库,但我不能用它们实现带有插入错误的自动建议函数


共 (1) 个答案

  1. # 1 楼答案

    在不了解任何细节的情况下,您的代码有两个明显的问题:

    1. 线性时间

    你的代码循环了每一个建议。如果可能的建议列表很长,那么迭代每一项都会变得令人无法接受的慢。您可以按某种顺序对建议进行排序和/或切断建议的最大数量

    1. 争用

    您的并行线程没有扩展。它们都在争夺getProssimo所持有的锁,然后只做很少的工作(我想),所以大多数情况下,多线程不会给您带来任何好处。通过让线程一次获得成批建议来减少争用