如何在序列中找到缺失的元素?

时间:2016-11-15 09:30:48

标签: java algorithm search

我有一个字符串arraylist,我需要传递来自[“AA00001”,“AA00005”,“AA00003”-----“ZZ00678”的 22184 元素,我需要生成列表中不存在的序列元素。我为此编写了代码,对于较少的输入,它生成了所需的输出。但是,当我添加22184个元素并想要生成200个唯一的ID时,这些ID不会出现在arraylist中,我会收到错误

方法main(String [])的代码超出65535字节限制

有人可以帮忙吗?

    import java.util.ArrayList;

public class GenerateIds
{
    private static ArrayList<String> ids = new ArrayList<>();
    static int n=50;  //no of Ids u want to generate
    static int completed =0;
    static char ID[] = new char[7];
    public static void main(String[] args)
    {
        ids.add("AA00001");
        ids.add("AA00004");
        ids.add("AA00007");
        generateIds(0);
        for(String id : ids)
        {
            System.out.println(id);
        }
    }


    private static void generateIds(int i)
    {
        if(n!=completed)
        {
            if(i<2)
            {
                for(char c ='A';c<'Z';c++)
                {
                    ID[i]=c;
                    generateIds(i+1);
                }
            }
            else if(i>=2 && i<7)
            {
                for(char c ='0';c<='9';c++)
                {
                    ID[i]=c;
                    generateIds(i+1);
                }
            }else if(i==7)
            {
                String id = String.valueOf(ID);
                if(!ids.contains(id))
                {
                    ids.add(id);
                    completed++;
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您可以将您的ID放在文本文件中。然后使用类似的东西。

List<String> ids = Files.readAllLines(Paths.get("ids.txt"));

答案 1 :(得分:0)

  

在java中,方法不能超过65535个字节。

由于您正在进行所有内联添加,因此主要方法变得过大:

ids.add("AA00001");
ids.add("AA00004");
ids.add("AA00007");
...

这将使主方法过长。您可以做些什么来解决这个(以及找到缺少的元素)将所有String值放在List中并循环遍历它以找到缺少的元素:

public void findMissingElements() {

    List<String> missingIds = allPossibleIds.stream()
                                            .filter(isMissingIn(existingIds))
                                            .collect(toList());

    //do something with the missingIds...

}

正如matt之类的其他读者所建议的那样,将所有字符串放在一个文件中并读取文件。

我写了一个小例子来展示它如何一起工作。我用jOOλ重写了你的generateIds方法以生成所有可能的id并将其重命名为allPossibleIds(但是你的递归方法也可以工作)。我将id限制为3位数字以限制搜索时间为例。

  public class FindMissingIdsTest {

  private List<String> allPossibleIds;
  private List<String> existingIds;

  @Before
  public void setup() throws IOException {
    allPossibleIds = allPossibleIds();
    existingIds    = retrieveIdsFromSubSystem();
  }

  @Test
  public void findMissingElements() {

    List<String> missingIds = allPossibleIds.stream()
                                            .filter(isMissingIn(existingIds))
                                            .collect(toList());

  }

  private Predicate<String> isMissingIn(List<String> existingIds) {
    return possibleId -> !existingIds.contains(possibleId);
  }

  public List<String> allPossibleIds(){
    List<String> alphabet = Seq.rangeClosed('A', 'Z').map(Object::toString).toList();
    List<String> letterCombinations = Seq.seq(alphabet).crossJoin(Seq.seq(alphabet)).map(t -> t.v1 + t.v2).toList();
    List<String> numbericParts = IntStream.range(0, 1000)
                                          .mapToObj(i -> String.format("%03d", i))
                                          .collect(toList());

    return Seq.seq(letterCombinations).crossJoin(Seq.seq(numbericParts)).map(t -> t.v1 + t.v2).toList();
  }

  public List<String> retrieveIdsFromSubSystem() throws IOException {
    return Files.readAllLines(Paths.get("ids.txt"));
  }

}

要再次更改为5位数,您只需将1000更改为100000,将%03d更改为%05d。

如果您可以订购列表,您可能会找到更快更好的算法。这一切都取决于具体情况。例如如果你有一个有序列表,你可以建立所有id的流,迭代它并用指针跟在现有列表中,而不是总是做一个消耗contains()的资源。