【问题标题】:Duplicates elements not removed from ArrayList复制未从 ArrayList 中删除的元素
【发布时间】:2013-12-05 12:24:39
【问题描述】:

我正在尝试使用以下代码将唯一元素添加到数组中。我使用了 Ignorecase,但我仍然得到重复。

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    public class RemoveDuplicatesIgnoreCase {

    public static void main(String args[]) {

        // String Array with duplicates Colors
        String[] colorArray={"Black","BLACK","black","Cobalt","COBALT","cobalt","IVORY","Ivory","ivory","White","WHITE","white"};
        List<String> uniqueColorList=new ArrayList<String>();
        for (String color : colorArray) {
            if(!uniqueColorList.contains(color)&& !uniqueColorList.contains(color.toLowerCase())&& !uniqueColorList.contains(color.toUpperCase()))
            {
                uniqueColorList.add(color);
            }
        }
        Iterator<String> itr=uniqueColorList.iterator();
        while(itr.hasNext())
        {
            System.out.println(itr.next());
        }

    }

}

输出:

Black
BLACK
Cobalt
COBALT
IVORY
White
WHITE

我想避免添加区分大小写和不区分大小写的重复项。

【问题讨论】:

  • 应该区分大小写吗?

标签: java arraylist


【解决方案1】:

我会使用 SET 而不是 ArrayList 并以小写形式添加字符串。 Set 不允许重复元素。

Set<String> uniqueColorList = new HashSet<String>();
for (String color : colorArray) {
    uniqueColorList.add(color.toLowerCase());
}

【讨论】:

  • 也许他需要在应用程序的其余部分使用 List
  • @user1021726 我认为这不太可能,但我同意他可能!
  • 考虑到一切都在他的main 中,是的,不太可能:P 但如果这是在更大的 API 或更大的程序中,您可能不想或无法更改数据类型
  • 你也不保留原案。
【解决方案2】:

您必须将两个值都小写才能找到匹配项

【讨论】:

    【解决方案3】:

    我认为正确的方法是将颜色封装在一个对象中。 这只是最小的开销,并使您的代码更具可读性:

    public class ColorString {
        public final String str;
    
        public ColorString(String str) {
          this.str = str;
        }
    
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (obj == this) return true;
            if (!(obj instanceof ColorString )) return false;
    
            ColorString col = (ColorString) obj;
    
            if (this.str == null) return (col.str == null);
    
            return this.str.equalsIgnoreCase(col.str);
        }
    
        public int hashCode() { // Always override hashCode AND equals
            return str.toLowerCase().hashCode();
        }
    
    }
    

    如果你这样做,你可以使用所有的标准方法,你可以使用 Set、ArrayList.contains 等等。这个解决方案更明智,因为它代表了这个想法:你没有字符串,但是你有一个“颜色”并且你有特殊的规则,当两个“颜色”应该被认为相等或不相等时。

    如果您想扩展您的解决方案,例如通过允许将具有相似名称的多种颜色视为相同的“颜色”,您只需更改一种方法,一切仍然有效!

    【讨论】:

      【解决方案4】:

      我会使用小写颜色的Set 来跟踪唯一性:

      public static void main(String args[]) {
      
          String[] colorArray={"Black","BLACK","black","Cobalt","COBALT","cobalt","IVORY","Ivory","ivory","White","WHITE","white"};
      
          List<String> colors = new ArrayList<String>();
          Set<String> uniqueColors = new HashSet<String>();
          for (String color : colorArray) {
              if (set.add(color.toLowerCase()) {
                  uniqueColors.add(color);
              }
          }
          // colors now contains case-insensitive unique names 
      }
      

      这段代码利用了关于Set的两件事:

      1. 集合只允许唯一值,因此通过放入字符串的小写副本,我们可以处理不区分大小写的部分
      2. 如果操作更改了集合,add() 方法将返回 true,仅当添加的值是集合中的新值时才会发生这种情况,使用此返回值可避免使用 contains() - 只需尝试添加值,您会发现它是否是唯一的。

      【讨论】:

        【解决方案5】:

        您的问题是您只涵盖所有小写和所有大写 Strings,而不包括任何其他大小写组合(例如,您也有大写的字符串)。

        为了简短起见,您可以扩展 ArrayList 并覆盖 contains 以对每个 String 使用忽略大小写比较,如 in this thread 建议的那样:

        import java.util.ArrayList;
        import java.util.Iterator;
        import java.util.List;
        
        public class RemoveDuplicatesIgnoreCase {
            public static void main(String args[]) {
        
                // String Array with duplicates Colors
                String[] colorArray={"Black","BLACK","black","Cobalt","COBALT","cobalt","IVORY","Ivory","ivory","White","WHITE","white"};
                List<String> uniqueColorList=new IgnoreCaseStringList<String>();
                for (String color : colorArray) {
                    if(!uniqueColorList.contains(color))
                    {
                        uniqueColorList.add(color);
                    }
                }
                Iterator<String> itr=uniqueColorList.iterator();
                while(itr.hasNext())
                {
                    System.out.println(itr.next());
                }
        
            }
        
        }
        
        public class IgnoreCaseStringList extends ArrayList<String> {
            @Override
            public boolean contains(Object o) {
                String paramStr = (String)o;
                for (String s : this) {
                    if (paramStr.equalsIgnoreCase(s)) return true;
                }
                return false;
            }
        }
        

        【讨论】:

          【解决方案6】:

          这不起作用,因为您首先添加了既不是大写也不是小写的黑色。

          您可以决定添加大写或小写字符串,更好的是,如果排序对您不重要,则使用 TreeSet。 TreeSet 将使其按字母顺序排序。

          【讨论】:

            【解决方案7】:

            原因是你检查所有小写字母

            当您检查 BLACK 时,列表中有 Black 但 Black != black。

            小写字符串的第一个字符是大写的。

            【讨论】:

              【解决方案8】:

              首先从这部分开始:

              uniqueColorList.contains(color)
              

              不起作用,这是因为当它对字符串执行 .equals 时,大小写不同。那么你的下一个问题是小写和大写不起作用,因为第一个如果混合。归根结底,WHITE 和 White 在技术上是独一无二的。按照 ZouZou 的建议,最简单的选择是只使用一个套盒。否则你需要按照 Domi 所说的去做并实现你自己的 contains 方法来进行不区分大小写的检查

              【讨论】:

                【解决方案9】:
                Set<String> duplicateDection = new HashSet<>()
                if (duplicateDection.add(color.toLowerCase())) {
                  uniqueColorList.add(color);
                }
                

                如果从列表中删除项目,您还需要将它们从重复检测中删除:

                uniqueColorList.remove(color);
                duplicateDetection.remove(color.toLowerCase());
                

                【讨论】:

                  【解决方案10】:

                  您只检查正在构建的列表是否已包含要添加的元素的“相同大小写”“大写”“小写”变体,因此如果列表已包含具有不同大小写组合的字符串,则搜索并不详尽然后它通过条件并添加颜色。

                  【讨论】:

                    【解决方案11】:

                    试试这个..

                    public static void main(String[] a) {
                        String[] colorArray = {"Black", "BLACK", "black", "Cobalt", "COBALT", "cobalt", "IVORY", "Ivory", "ivory", "White", "WHITE", "white"};
                        List<String> uniqueColorList = new ArrayList<String>();
                    
                        for (int i = 0; i < colorArray.length; i++) {
                            for (int j = i+1; j < colorArray.length; j++) {
                                if (!colorArray[i].equals("")) {
                                    if (colorArray[i].equalsIgnoreCase(colorArray[j])) {
                                        colorArray[j] = "";
                                    }
                                }
                            }
                        }
                        System.out.println(Arrays.toString(colorArray));;
                        for (String color : colorArray) {
                            if (!color.equals("")) {
                                uniqueColorList.add(color);
                            }
                        }
                        Iterator<String> itr = uniqueColorList.iterator();
                        while (itr.hasNext()) {
                            System.out.println(itr.next());
                        }
                    }
                    

                    【讨论】:

                      【解决方案12】:
                      I want to avoid adding case sensitive & case insensitive duplicates.
                      

                      当您比较字符串与比较值相同时,您必须将所有字符串转换为小写或大写。

                      你可以使用equalsIgnoreCase()

                      但更好更简单的方法是使用Set,因为它只保留唯一的值。

                      Set<String> uniqueVal = new HashSet<String>();
                      for (String color : colorArray) {
                          uniqueVal.add(color.toLowerCase());
                      }
                      

                      您可以再次将Set 转换为List

                      List<String> uniqueList=new ArrayList<>(uniqueVal); 
                      // Now list contains unique values only 
                      

                      【讨论】:

                        【解决方案13】:
                        public static void main(String args[]) {
                        
                            String[] colorArray={"Black","BLACK","black","Cobalt","COBALT","cobalt","IVORY","Ivory","ivory","White","WHITE","white"};
                            Set<String> uniqueColorList = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
                            for (String color : colorArray) {
                                    uniqueColorList.add(color);
                            }
                            Iterator<String> itr=uniqueColorList.iterator();
                            while(itr.hasNext())
                            {
                                System.out.println(itr.next());
                            }
                        
                        }
                        

                        这会解决你的问题

                        输出:

                        Black
                        Cobalt
                        IVORY
                        White
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2013-02-24
                          • 2022-01-17
                          • 2014-09-19
                          • 1970-01-01
                          相关资源
                          最近更新 更多