【问题标题】:How to find the missing elements in a sequence?如何找到序列中缺失的元素?
【发布时间】:2017-03-29 03:03:39
【问题描述】:

我有一个字符串数组列表,我需要从 ["AA00001", "AA00005" ,"AA00003" ----- "ZZ00678"] 传递 22184 元素,我需要生成列表中不存在的序列元素。我已经为此编写了代码,并且对于较少的输入,它正在生成所需的输出。但是当我添加 22184 个元素并想要生成 200 个不存在于 arraylist 中的唯一 id 时,我收到了错误

方法 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++;
                }
            }
        }
    }
}

【问题讨论】:

  • 该代码绝对没有超过 64k 的限制。它runs fine on ideone.
  • 你可以把你的身份证放在一个文本文件中,然后读取文本文件。
  • 如果你在你的 main 方法中做所有的ids.add("AA00001"); ids.add("AA00004"); ids.add("AA00007");... &lt;many more&gt;,它很容易超过限制,因为它变得太大了。最好有一个包含所有 ID 的外部文件并将其读入您的列表。
  • 我想失败的代码有 22000 多个语句,例如 ids.add("...")。如果是这种情况,您是否考虑过将这个 id 列表放在一个文件中并读取它而不是把它们放在源代码中?
  • 该代码编译并运行完美,没有错误。

标签: java algorithm search


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    main 方法变得太大,因为您正在内联执行所有添加:

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

    这会使 main 方法过长。您可以做些什么来解决这个问题(并找到丢失的元素) 将所有 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()

    【讨论】:

      猜你喜欢
      • 2018-04-20
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2011-07-12
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多