sanjay gupta Ответов: 2

Почему для циклов требуется много времени для выполнения в следующей программе


в этой программе я дал wikipeadia URL для логики извлечения текста, но после извлечения текста "для циклов" требуется много времени для выполнения.
та же логика слишком быстра в программе python.

как сократить время выполнения?


import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TextExtraction1 
{
	static TextExtraction1 fj;
	public String toHtmlString(String url) throws IOException 
	{
		StringBuilder sb = new StringBuilder();
		   for(Scanner sc = new Scanner(new URL(url).openStream()); sc.hasNext(); )
		      sb.append(sc.nextLine()).append('\n');
		   return sb.toString();
	}
	
	static int search(String key,String target)
	{
		int count=0;
		Pattern p=Pattern.compile(key);
		Matcher m=p.matcher(target);
		while(m.find()){count++;}
		return count;
	} 

	String extractText(String s) throws IOException
	{
				 
		String h1 = fj.toHtmlString(s); 
        System.out.println("extracted \n\n");
        int i2=0;
        String h2[] = h1.split("\n");
        String html="";
        long start = System.currentTimeMillis();
        
        for(String h3:h2)
        {	//bw.write(h3);bw.newLine();
        		html += h3;
                html += ""; //iu=iu+1;               	
        }
        long end = System.currentTimeMillis();
        System.out.println(++i2+" th loop end in "+(end-start)/1000+" seconds");
        boolean capture = true;
        String filtered_text = "";
        
        String html_text[] = html.split("<");
        String h_text[];//System.out.println("kyhe1");
        
        
        start = System.currentTimeMillis();
        for(String h:html_text)
        {
        	h = "<" + h;
        	h_text = h.split(">");
        	for(String w :h_text)
        	{
        		if(w.length()>0)	{	if(w.substring(0, 1).equals("<")){w +=">";}	}
        		if(search("</script>",w)>0){capture=true;}
        		else if(search("<script",w)>0){capture=false;}
        		else if(capture){filtered_text += w;     filtered_text += "\n";}
        	}
        }
       // System.out.println("kyhe1");
        end = System.currentTimeMillis();
        html_text = filtered_text.split("\n");
        
        System.out.println(++i2+" th loop end in "+(end-start)/1000+" seconds");
        return html_text[0];
	}
	
		
	public static void main(String []args)throws IOException 
	{
		fj = new TextExtraction1();
		System.out.println(fj.extractText("https://en.wikipedia.org/wiki/Varanasi"));
	}
}



Тот же самый код python слишком быстр


import urllib2
import re
import sys
def get_text(f1):                #(f1)
    h1 = f1.read()        #f1.read()
    html = ''                # h3 is a string 
    h2 = h1.split('\n')
    f= open("guru99.txt","w+")
    
    for h3 in h2:
        html += h3
        html += ' '
        
           
    capture = True
    filtered_text = ''
    html_text = html.split('<')
   
    i=0
    for h in html_text:
        h = '<' + h
        h_text = h.split('>')
        
        for w in h_text:           
            if w:
                if w[0] == '<':
                    w += '>'
                    
            if re.search(r'</script>', w):
                capture = True                
            elif re.search(r'<script', w):
                capture = False                
            else:
                if capture:
                    filtered_text += w
                    filtered_text += '\n'
   
def get_url_text(url):
    
    try :
        f = urllib2.urlopen(url)
    except (urllib2.HTTPError,urllib2.URLError) :
        return '\n'
    else:
        return get_text(f)
def main():
    get_url_text(sys.argv[1])
if __name__ == "__main__": main()


Что я уже пробовал:

я только что преобразовал "for loop" в while loop


String h3="";int i3=0;
        while(i3<h2.length)
        {	//bw.write(h3);bw.newLine();
        		h3=h2[i3];
        		html += h3;
                html += "";i3++; //iu=iu+1;               	
        }

2 Ответов

Рейтинг:
0

Jochen Arndt

Вы должны попытаться оптимизировать Java-код.

Наилучшей оптимизации можно достичь, избегая создания динамических объектов внутри циклов.

Пример:

# PHP
if w:
    if w[0] == '<':
        w += '>'

// Java
if(w.length()>0)
{	
    if(w.substring(0, 1).equals("<"))
    {
        w +=">";
    }	
}

Ее substring создаст новую строку динамически и выполнит сравнение строк.
Почему бы просто не использовать String.charAt() и провести сравнение персонажей?
if(w.length()>0)
{	
    if(w.charAt(0) == '<')
    {
        w += ">";
    }	
}

Другой оптимизацией может быть использование класса или статических членов для хранения используемого поиска регулярных выражений PatternС. Затем Pattern.compile() не должен быть выполнен несколько раз.


Afzaal Ahmad Zeeshan

Не уверен и слишком ленив для Google, но разве вы не можете применить индексаторы в Java, чтобы получить символ в этом индексе в строковых объектах? Просто любопытно. :-)

Jochen Arndt

Мне тоже придется погуглить.

Индексатор был бы лучше при итерации по символам, потому что он избегает проверки привязки. Здесь потребовалось бы разделить цикл на два, а затем обработать символы и подстроки.

Afzaal Ahmad Zeeshan

Да, я тоже огляделся и нашел только charAt доступно в Java API, тогда как они могли бы написать интерфейс, который допускает такую возможность.

Ваш ответ был хорош, и мой комментарий был просто еще одним быстрым вопросом только к вам, ничего о посте. 5ед за это. :-)

Рейтинг:
0

Patrice T

Существует инструмент, который позволяет узнать, где программа проводит время, его название-Profiler.
Профилирование (компьютерное программирование) - Википедия[^]

Вы должны попробовать использовать StringBuilder каждый раз, когда вам приходится соединять строки.
Обратите внимание, что

filtered_text += w;     filtered_text += "\n";

медленнее, чем
filtered_text += w + "\n";