有 Java 编程相关的问题?

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

从java字符串数组中获取2个元素的所有组合

假设我有这个数组列表['a','b','xx']。 我想提取每2个字符串组合(每2个元素)。例如['a','b']['a','xx']['b','a']['b','xx']['xx','a']['xx','b']

我已经写了这段代码,但是当数组变得非常大时(对于 示例)GC内存不足

        private Text empty = new Text("");

    public void start(Iterable<Text> values,Context context) throws {
        List<String> sitesArr = new ArrayList<String>();
        HashMap<String, String> hmapPairs = new HashMap<String, String>();

        for (Text site : values){
            sitesArr.add(site.toString());
        }

        insertPairsToHash(hmapPairs, sitesArr);
        writeContextFromHash(hmapPairs, context);
    } 

    private void insertPairsToHash(HashMap<String, String> hmapPairs, List<String> sitesArr) {
        for (int i=0; i<sitesArr.size(); i++) {
            for (int j=i+1; j<sitesArr.size(); j++) {
                String firstPair = sitesArr.get(i) + "_" + sitesArr.get(j);
                String secondPair = sitesArr.get(j) + "_" + sitesArr.get(i);
                hmapPairs.put(firstPair,secondPair);
            }      
        }
    }

    private void writeContextFromHash(HashMap<String, String> hmapPairs, Context context) throws IOException, InterruptedException {
        Text textTowriteToFile = new Text("");
        for(Map.Entry<String, String> entry : hmapPairs.entrySet()) {
            textTowriteToFile.set(entry.getKey());
            context.write(textTowriteToFile, empty);
            textTowriteToFile.set(entry.getValue());
            context.write(textTowriteToFile, empty);
        }
    }

我使用2作为循环,在每次迭代中,我向散列中插入两个组合(['a'、'b']和['b','a']第一个元素是键,第二个是值,所以在['a','b']'a'将是键,'b'将是值,反之亦然)。 然后我在散列上迭代一次以发送值。 如何在使用更少内存的情况下提高速度


共 (1) 个答案

  1. # 1 楼答案

    你可以简单地重构你的类流结果。所以你不需要保留组合元素结果的完整列表

        private Text empty = new Text("");
    
       public void start(Iterable<Text> values,Context context) throws IOException, InterruptedException  {
           List<String> sitesArr = new ArrayList<String>();
    
           for (Text site : values){
               sitesArr.add(site.toString());
           }
           insertPairsToHash(sitesArr,context);
       } 
    
       private void insertPairsToHash(List<String> sitesArr, Context context) {
           for (int i=0; i<sitesArr.size(); i++) {
               for (int j=i+1; j<sitesArr.size(); j++) {
                   String firstPair = sitesArr.get(i) + "_" + sitesArr.get(j);
                   String secondPair = sitesArr.get(j) + "_" + sitesArr.get(i);
    
                   doWrite(context, firstPair, secondPair);
               }      
           }
       }
    
        private void doWrite(Context context, String firstPair, String secondPair) {
            Text textTowriteToFile = new Text("");
               textTowriteToFile.set(firstPair);
               context.write(textTowriteToFile, empty);
               textTowriteToFile.set(secondPair);
               context.write(textTowriteToFile, empty);
        }
    

    这将降低内存使用率

    一般来说,如果您的输入很大或没有限制,您会尝试对结果进行流式处理,流式处理会增加一些复杂性,但会使内存使用独立于您输入的大小

    编辑(评论后):

    可以通过从列表中删除已使用的元素来删除它们。 在这种情况下,您应该使用LinkedList而不是ArrayList,因为从数组列表中删除head元素将需要比从链接列表中执行相同操作更多的GC和CPU时间

    然而,这不会降低峰值内存使用率,只会随着时间的推移降低使用率(随着进程的进行,您将需要更少的内存)

    如果其他组件在处理过程中消耗更多内存,那么它仍然很有用

     List<String> sitesArr = new LinkedList<>();
    
    private void insertPairsToHash(List<String> sitesArr, Context context) {
        while (!sitesArr.isEmpty()) {
            String left = sitesArr.remove(0);
            for (String right : sitesArr) {
                String firstPair = left + "_" + right;
                String secondPair = right + "_" + left;
                doWrite(context, firstPair, secondPair);
            }
        }
    }