【问题标题】:Sorting an array with Bi Predicate使用 Bi Predicate 对数组进行排序
【发布时间】:2020-04-19 11:50:13
【问题描述】:

我试图采用已排序的 File[] 数组(应用了特定的排序条件) 我尝试对与第一次排序具有相似排序结果的不同对象应用额外排序(例如 - 文件大小)。

我写了以下代码,但是没有用:

private static void sameValueHandler(File[] orderedFiles, BiPredicate<File,File> sortingCondition){ 
        for(int i = 0; i < orderedFiles.length - 1; i++){
            int j;
            for (j = i + 1; j < orderedFiles.length ; j++){
                if (!sortingCondition.test(orderedFiles[i],orderedFiles[j])){
                    if (j - i - 1> 1){
                        File[] sameFiles = new File[j - i - 1];
                       System.arraycopy(orderedFiles, i, sameFiles, 0,j - i - 1);
                       sameFiles = MainOrder.defaultOrd(sameFiles); // Calls a method that sorts (files by file.getAbsolutePath())

                       System.arraycopy(sameFiles, 0, orderedFiles, i,j - i - 1);
                   }else{
                       break;
                   }
                }
            }
            i = j;

        }
    }

基本上,我要做的就是检查来自orderedFiles 的哪些文件与给定的BiPredicate 共享相同的sortingCondition,并使用MainOrder.defaultOrd() 对这些文件进行排序,按file.getAbsolutePath() 排序,所以结果应该是一个排序数组,最初使用给定的 BiPredicate 排序(假设 File[] orderedFiles 已经排序) - 然后使用 deafaultOrd 方法重新处理共享相同排序条件的文件,同时保留具有唯一排序条件的原始文件导致地点。

例如:

假设我在orderedFiles 中有以下文件:

-file2.txt

-file1.txt

-file5.txt

-file6.txt

并且file1和file2共享相同的fileSize,但是file2.getAbsolutePath().compareTo(file1.getAbsolutePath()) &gt; 0

我想使用数组,使 file2 出现在 file1 之后:

-file1.txt

-file2.txt

-file5.txt

-file6.txt

希望我已经足够清楚了。谢谢!

编辑:

也尝试使用冒泡排序,但效果不佳:

 private static void sameValueHandler(File[] orderedFiles, BiPredicate<File,File> sortingCondition){
        //TODO fix.
        int arrLength = orderedFiles.length;
        for(int i = 0; i<arrLength-1; i++){
            for(int j=0; j<arrLength-i-1;j++){
                if(sortingCondition.test(orderedFiles[j],orderedFiles[j+1])){
                    if(orderedFiles[j].getAbsolutePath().compareTo(orderedFiles[j+1].getAbsolutePath()) > 0){
                        File temp = orderedFiles[j];
                        orderedFiles[j] = orderedFiles[j+1];
                        orderedFiles[j+1] = temp;

                    }
                }
            }
        }

【问题讨论】:

    标签: java sorting


    【解决方案1】:

    你可以用一个排序来做到这一点。您需要按如下方式对数组进行排序:

        Arrays.sort(orderedFiles,
                    Comparator.comparing(File::length)
                            .thenComparing(
                                    File::getAbsolutePath));
    

    Arrays.sort 的第二个参数是 comparator,您可以在 JavaDocs 中阅读。

    首先它按长度排序,如果它们相等,则按路径排序。您可以根据需要链接任意数量的 thenComparing 方法。如果文件已经在第一个字段上排序,则影响最小。它仍然可以正常工作。或者你可以这样做:

         Arrays.sort(orderedFiles,
                 Comparator.comparing(File::getAbsolutePath));
                            .
    

    这是一个处理一些虚构数据的示例。当您运行它并打印出排序列表时,您可以看到它是如何排序的,首先是 value,然后是名称的 length

            List<Example> data = new ArrayList<>(
                    List.of(new Example(20, "watermelon"),
                            new Example(20, "apple"),
                            new Example(20, "peaches"),
                            new Example(10, "grapes"),
                            new Example(100, "house"),
                            new Example(100, "apartment")));
            data.sort(Comparator.comparing(Example::getValue)
                    .thenComparing(a -> a.getName().length()));
    
            data.forEach(System.out::println);
    
    
    
        class Example {
            private int value;
            private String name;
    
            public Example(int value, String name) {
                this.value = value;
                this.name = name;
            }
    
            public String getName() {
                return name;
            }
    
            public int getValue() {
                return value;
            }
    
            public String toString() {
                return value + " " + name;
            }
    
    
    
    

    【讨论】:

      【解决方案2】:

      首先您必须了解比较器的工作原理 (from Java docs):

      if file1 > file2, it returns positive number  
      if file1 < file2, it returns negative number  
      if file1 == file2, it returns 0  
      

      这么说:

          public static Comparator<File> secondSort = (f1, f2) -> {
              // apply the second sort rules and return -1, 0, 1 based on Comparator returns
              return 0; // -1, 0, 1
          };
      
          public static Comparator<File> sortIt = (f1, f2) -> {
              // check if files are equals base in your first rule
              boolean filesAreEquals = true;
      
              if (filesAreEquals) {
                  return secondSort.compare(f1, f2);
              }
              return 0;
          };
      
          private static void sameValueHandler(File[] orderedFiles) 
          {        
              List<File> ordered = Arrays.
                      stream(orderedFiles).
                      sorted(sortIt::compare).
                      collect(Collectors.toList());
          }
      

      它允许您将不同的比较器传递给您的方法并更改元素的排序方式。

      【讨论】:

        【解决方案3】:

        您可以将Arrays.sort(T[], Comparator) 与以下Comparator 一起使用,先按文件长度排序,然后按文件路径排序(如果文件长度相等):

        File[] files = ...;
        Arrays.sort(files, new Comparator<File>() {
            @Override
            public int compare(File f1, File f2) {
                int result = Long.compare(f1.length(), f2.length());
                if(result == 0) {
                    result = f1.getAbsolutePath().compareTo(f2.getAbsolutePath());
                }
                return result;
            }
        });
        

        【讨论】:

        • 谢谢,但我真的很想在使用 BiPredicate 功能接口时解决这个问题。介意看看我的冒泡排序,看看为什么没有成功?
        猜你喜欢
        • 2012-01-26
        • 1970-01-01
        • 2021-11-02
        • 2012-11-14
        • 2014-12-11
        • 2016-05-05
        相关资源
        最近更新 更多