Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从未排序的输入返回唯一值的算法_Java_Algorithm_Unique - Fatal编程技术网

Java 从未排序的输入返回唯一值的算法

Java 从未排序的输入返回唯一值的算法,java,algorithm,unique,Java,Algorithm,Unique,我需要创建一个高效的算法,从未排序的输入返回唯一的值。我不知道输入的长度 由于调用此算法的函数可以随时中止读取,因此我认为使用定义良好的Iterable实现是正确的方法,因此我不会为非需要的输入浪费额外的处理能力 今天,我使用集合来跟踪我已经读取的值。但我不知道这是否是最有效的算法,因为我的输入长度可能很大 下面的代码是我今天的工作算法: import java.util.Iterator; import java.util.HashSet; import java.util.Set; impo

我需要创建一个高效的算法,从未排序的输入返回唯一的值。我不知道输入的长度

由于调用此算法的函数可以随时中止读取,因此我认为使用定义良好的
Iterable
实现是正确的方法,因此我不会为非需要的输入浪费额外的处理能力

今天,我使用
集合
来跟踪我已经读取的值。但我不知道这是否是最有效的算法,因为我的输入长度可能很大

下面的代码是我今天的工作算法:

import java.util.Iterator;
import java.util.HashSet;
import java.util.Set;
import java.util.NoSuchElementException;
import java.io.BufferedReader;
import java.io.StringReader;
import java.io.IOException;

public class UniqueValues implements Iterable<String> {
    private final Iterator<String> iterator;

    public UniqueValues(BufferedReader r) {
        this.iterator = new UniqueValuesIterator(r);
    }

    public Iterator<String> iterator() {
        return iterator;
    }

    static class UniqueValuesIterator implements Iterator<String> {
        private final BufferedReader r;

        private final Set<String> values = new HashSet<>();

        // When 'next' is null, need to get the next value
        private String next;

        public UniqueValuesIterator(BufferedReader r) {
            this.r = r;
        }

        public boolean hasNext() {
            // Good point from OldCurmudgeon
            if(next != null) return true;

            try {
                String line;
                while((line = r.readLine()) != null) {
                    if(values.add(line)) { // add() returns 'true' when it is not a duplicate value.
                        next = line;
                        return true;
                    }
                }
            } catch(IOException e) { }

            return false;
        }

        public String next() {
            if(next == null) {
                if(! hasNext() ) throw new NoSuchElementException();
            }

            final String temp = next;
            next = null;
            return temp;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    // For testing
    public static void main(String... args) {
        final StringReader r = new StringReader("value1\nvalue6\nvalue1\nvalue3\nvalue3\nvalue6\nvalue1\nvalue6");

        for(final String value : new UniqueValues(new BufferedReader(r)) ) {
            System.out.println(value);
        }

        /* Output is (order is not important):
         * 
         * line 1
         * line 6
         * line 3
         */
    }
}
import java.util.Iterator;
导入java.util.HashSet;
导入java.util.Set;
导入java.util.NoSuchElementException;
导入java.io.BufferedReader;
导入java.io.StringReader;
导入java.io.IOException;
公共类UniqueValues实现了Iterable{
私有最终迭代器;
公共唯一值(BufferedReader r){
this.iterator=新的UniqueValuesIterator(r);
}
公共迭代器迭代器(){
返回迭代器;
}
静态类UniqueValuesIterator实现迭代器{
专用最终缓冲读取程序r;
私有最终集值=新HashSet();
//当“next”为空时,需要获取下一个值
私有字符串下一步;
公共唯一估值器(BufferedReader){
这个。r=r;
}
公共布尔hasNext(){
//OldCurmudgeon的观点很好
if(next!=null)返回true;
试一试{
弦线;
而((line=r.readLine())!=null){
if(values.add(line)){//add()在不是重复值时返回'true'。
下一个=行;
返回true;
}
}
}捕获(IOE){}
返回false;
}
公共字符串next(){
if(next==null){
如果(!hasNext())抛出新的NoSuchElementException();
}
最终字符串温度=下一个;
next=null;
返回温度;
}
公共空间删除(){
抛出新的UnsupportedOperationException();
}
}
//用于测试
公共静态void main(字符串…参数){
最终StringReader r=新StringReader(“值1\nvalue6\nvalue1\nvalue3\nvalue3\nvalue6\nvalue1\nvalue6”);
for(最终字符串值:新的唯一值(新的BufferedReader(r))){
系统输出打印项次(值);
}
/*输出为(顺序不重要):
* 
*第1行
*第6行
*第3行
*/
}
}

它是否有更好的算法来实现这一点?

这似乎很好,但是我很想让代码不那么通用,除非您经常这样做

try(BufferedReader br = new BufferedReader(new FileReader(file))) {
     Set<String> lines = new HashSet<>();
     for(String line; (line = br.readLine()) != null;) {
        if(lines.add(line)) {
            // do something
        }
     }
 }
try(BufferedReader br=new BufferedReader(new FileReader(file))){
Set line=new HashSet();
for(字符串行;(line=br.readLine())!=null;){
如果(行。添加(行)){
//做点什么
}
}
}
或者,如果您必须返回一个Iterable,您可以这样做

public static Set<String> uniqueLines(File file) {
    try(BufferedReader br = new BufferedReader(new FileReader(file))) {
         Set<String> lines = new HashSet<>();
         for(String line; (line = br.readLine()) != null;)
            lines.add(line))
         return lines;
     }
 }
公共静态设置唯一行(文件){
try(BufferedReader br=new BufferedReader(new FileReader(file))){
Set line=new HashSet();
for(字符串行;(line=br.readLine())!=null;)
行。添加(行))
回流线;
}
}

如果您的输入仅由字符串组成,您可以使用来跟踪它们。它具有O(字符串长度)查找和插入时间,并且比哈希映射更节省空间


不过有一点需要注意:trie在每个树节点上都有相当大的开销,因此只有当输入足够大且其元素足够相似时,它才会变得更加有效。例如,它不会给随机生成的字符串带来任何好处。

如果(next!=null)您应该使用
if(next!=null)
保护您的
hasNext
。用户可以随意调用
hasNext
,而不调用
next
。在这种情况下,您将转到下一项。@dudinha dedalus,Set has iterator()方法,它可以返回iterate ablecollection@dudinha-dedalus不清楚为什么这是一个要求,但您可以使用第二个示例。@PeterLawrey在第二个示例中,代码将读取所有输入(可能很大),主代码需要很长时间才能开始处理某些内容。使用我的方法,只要有唯一的数据,主代码就可以处理,如果不需要更多的数据,就可以停止使用迭代器。这有意义吗?@dudinha dedalus这是有意义的,但是线程完成的工作量可能是相同的,并且它可能会使用一种或另一种方法提前完成,这取决于它的使用方式。