需要使用集合按名称对颜色进行排序,并且为十六进制值

时间:2014-02-27 15:54:16

标签: java collections arraylist map hashmap

我正在尝试编写一个程序,该程序从输入文件读取并按其十六进制值对颜色进行配对。例如:黑色000000将是一对。以下是我到目前为止的情况:

public class HexColors{
public static void main(String[] args) throws IOException {
    ArrayList <String> colorsArray = new ArrayList<String>();
    Scanner hexColors = new Scanner(new File("input.txt"));

    while (hexColors.hasNext()) {
        colorsArray.add(hexColors.nextLine());
    }

// Assuming I have to use a map to accomplish this.
    Map<String, String> hexMap = new HashMap<String, String>(); 


    System.out.println("Test" + hexMap);

    System.out.print("The colors entered were:\n" );
    for (Iterator<String> itr = colorsArray.iterator(); itr.hasNext();)
        System.out.print(itr.next() + "\n");
    Collections.sort(colorsArray);
    System.out.println("The colors sorted by name are:");
    for(String colorsSorted : colorsArray){
        System.out.println(colorsSorted);
        }
    }
}

现在我按照颜色的自然顺序显示它,通过使用collections.sort,我也按字母顺序显示它们。重要提示:我不是在寻找一个完整的解决方案,只是关于我接下来应该去哪里的一些指示。是否可以将input.txt中的输入存储为Map?或者我应该以某种方式将ArrayList转换为地图?谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

如果您的输入文件每行包含一个颜色对,则更容易逐行读取文件BufferedReader(请参阅BufferedReader.readLine())然后拆分每行以提取颜色名称和十六进制值。

Reader reader = new BufferedReader(new FileReader("input.txt"));
String line;
while((line = reader.readLine()) != null) {
  // Split line
  // Add color name and hex value to your data structure
}

分割这样一条线有很多种方法。例如。你可以使用String.split()。 或者,您可以通过String.indexOf()搜索空格字符位置,然后使用String.substring()提取部分。

对于您的数据模型,也有很多替代方案。 HashMap可能是一个好主意,因为您始终拥有映射到十六进制值的颜色名称。您确定每个颜色名称在您的文件中是唯一的吗?

但仅使用HashMap您将丢失原始订单。更合适的数据结构是LinkedHashMap,它在内部使用双向链表来保存插入顺序。

因此,使用LinkedHashMap,您已完成第一个用例(原始订单)。迭代LinkedHashMap,你就完成了。

迭代Map的最佳方法是使用entrySet()

for(Entry<String, String> colorPair : map.entrySet()) {
  String colorName = colorPair.getKey();
  String colorHex = colorPair.getValue();
  // Process colorName and colorHex ...
}

对于字母顺序,您可以获取地图keySet()的所有条目,并将其放入ArrayList并使用Collections.sort()。然后迭代ArrayList并通过地图检索十六进制值。听起来有点复杂。但这是可行的。

但困难的部分是自然颜色顺序(你的意思是按十六进制值排序,对吧?)。因此,您可以通过Map.values()获取所有颜色十六进制值,对它们进行排序......

你不能反过来使用地图。在这里,您希望通过十六进制值检索颜色名称,但颜色名称是地图的键。我假设您不想使用第三方库,并且Java的标准库中没有双向映射。

当然你可以使用第二张还原地图,但也许我们应该在开始时重新考虑使用地图作为数据模型的选择。

更简单的方法是创建自己的ColorPair类,然后使用简单的ArrayList来保存所有颜色对。插入所有颜色对后,列表具有原始顺序。然后,您可以使用Collections.sort()按颜色名称排序,然后按颜色十六进制值。

这将是一个简单的ColorPair实现:

class ColorPair {
  private String name;
  private String hex;

  public ColorPair(String name, String hex) {
    this.name = name;
    this.hex = hex;
  }

  public String getName() {
    return name;
  }

  public String getHex() {
    return hex;
  }

  @Override
  public String toString() {
    return String.format("[ColorPair name=%s, hex=%s]", name, hex);
  }
}

您可以在此处实施Comparable界面,并为ColorPair个实例定义默认订单。但是你想要两个不同的命令,所以你必须使用Comparator类来Collections.sort()。 (您可以尝试将其作为练习。)

假设您有一个方法parseColorPair(),它接受​​一行输入文件并返回一个ColorPair实例,您可以这样读取您的文件:

Reader reader = new BufferedReader(new FileReader("input.txt"));
String line;
List<ColorPair> colorPairs = new ArrayList<ColorPair>();
while((line = reader.readLine()) != null) {
  colorPairs.add(parseColorPair(line));
}

// Output in original order
for(ColorPair colorPair: colorPairs) {
  System.out.println(colorPair); // using our custom ColorPair.toString() method
}

要按颜色名称对列表进行排序,您必须实现界面Comparator<ColorPair>

Collections.sort(colorPairs, new Comparator<ColorPair>() {
  public int compare(ColorPair colorPair1, ColorPair colorPair2) {
    // Compare the names of colorPair1 and colorPair2 and return
    // a negative value, if colorPair1.getName() is lesser than colorPair2's name.
    // return a positive value (greater than 0) if the first name is greater than
    // the second name and return 0 if the names are equal.
    // Hint: Look for String.compare()
  }
});

如果没有Collections.sort(),则无法使用Comparator版本,因为您的ColorPair类未实现Comparable<ColorPair>接口。

按十六进制值排序是类似的。 Comparator实现的不同之处仅在于比较十六进制值而不是名称。

因此,使用正确的数据结构可以直接实现用例,但为给定问题找到正确的数据结构并非易事。