我一直在解决这个问题。但是,我的数据排列略有不同。
无需讨论如何检索数据,只要说结果数组看起来像这样就足够了
String[2][]
[0] = String[4]
[1] = String[4]
实际数据如下
data = String[2][]
data[0]
data[0][0] = "Columbia"
data[0][1] = "Chile"
data[0][2] = "Asia"
data[0][3] = "US"
data[1]
data[1][0] = "B216"
data[1][1] = "B217"
data[1][2] = "A442"
data[1][3] = "N665"
我想按 data[0] 按字母顺序对整个数组进行排序。然而我意识到所引用的 SO 问题中提供的解决方案正在使用不同的数组格式。
我的预期结果会是这样的
data = String[2][]
data[0]
data[0][0] = "Asia"
data[0][1] = "Chile"
data[0][2] = "Columbia"
data[0][3] = "US"
data[1]
data[1][0] = "A442"
data[1][1] = "B217"
data[1][2] = "B216"
data[1][3] = "N665"
我不完全确定如何在不迭代每个元素并将它们转移到新数组的情况下获得这些结果。
有什么想法吗?
完整代码这里
String[]
的内部 data
进行排序。将
data
添加到 ArrayList
List<String[]> list = new ArrayList<>();
// Sort the String array and insert it in List
for (String dataArr[] : data) {
String s[] = dataArr.clone(); // create new object of String array
Arrays.sort(s); // Sort newly created String array
list.add(s);
}
使用自定义比较器对此列表进行排序。
3.1 请记住,您需要扫描比较中的两个数组的整个
String[]
才能找到第一个差异。
// Sort the list using custom comparator
Collections.sort(list, new Comparator<String[]>() {
@Override
public int compare(String[] o1, String[] o2) {
// optional: condition to check for string length equality
if (o1.length == o2.length) {
for (int i = 0; i < o1.length; i++) {
if (o1[i].equals(o2[i])) { // ** IMP **
// allows scanning through entire string array.
continue;
}
// Find the first different strings in both arrays
return o1[i].compareTo(o2[i]);
}
} else if (o1.length < o2.length) {
// allow string arrays with lesser elements to appear first
return -1;
} else if (o1.length > o2.length) {
return 1;
}
// When o1.length == o2.length and all strings are equal
return 0; // no difference
}
});
我可以看到如何将多个数组按相同顺序排序的三个选项:
创建一个索引数组,使用
Comparator
对其进行排序,Integer[] indices = new Integer[data[0].length];
for(int i = 0; i < data[0].length; i++)
indices[i] = i;
Arrays.sort(indices, new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
return data[0][i1].compareTo(data[0][i2]);
}
});
指的是要根据索引进行排序的数组,然后根据排序后的索引重新排列数组。这是一个示例:
Integer
索引数组必须是
int
类型而不是 Arrays
类型,因为 public String[] rearrange(Integer[] indices, String[] input) {
String[] output = new String[];
for(int i = 0; i < indices.length; i++)
output[i] = input[indices[i]];
return output;
}
不允许使用自定义比较器对基元进行排序。然后,您可以通过索引数组重新排列两个数组,执行类似于下面的函数的操作。我想不出一种方法可以在不打乱顺序并使索引数组无效的情况下就地执行此操作。
for(int i = 0; i < data.length; i++)
data[i] = rearrange(indices, data[i]);
此函数不会进行错误检查以查看输入是否具有相同的长度,并且它不使用流,我确信可以重写它来做到这一点。这只是这个概念的一个例子。使用方法:
Comparable
这可能是重新排列数组时占用内存最少的选项。它的灵感来自于这个答案对
创建一个对象来保存给定索引处的所有元素,并使其成为
public class Container implements Comparable<Container>
{
public final String country;
public final String code;
public Container(Sting country, String code)
{
this.country = country;
this.code = code;
}
public int compareTo(Container other)
{
return this.country.compareTo(other.country);
}
}
。这是之前提到的问题的已接受答案的解决方案。
objects = new Container[data[0].length];
for(int i = 0; i < objects.length; i++)
objects[i] = new Container(data[0][i], data[1][i]);
Arrays.sort(objects);
您必须将数据转换为这些容器的数组,然后对其进行排序:
List
虽然此方法确实需要将数据复制为不同的格式,但它实际上比使用数组数组更强大,因为它将概念上相关的项目分组为单个项目。这完全消除了检查数组长度是否相等之类的需要,并且通常更加面向对象。您甚至可以重写数据输入以仅吐出一个数组或
Container
对象,而不是 2D 数组。在国家/地区和代码之间创建显式映射,然后根据排序的键取消引用值。这有点像 #1 所做的,但它至少允许您就地对其中一个数组进行排序。如果映射是有序映射,直接转成有序数组即可。
a.未排序的映射:
HashMap<String, String> mapping = new HashMap<>();
for(int i = 0; i < data[0].length; i++)
mapping.put(data[0][i], data[1][i]);
Arrays.sort(data[0]);
String[] outputCodes = new String[data[1].length];
for(int i = 0; i < outputCodes.length; i++)
outputCodes[i] = mapping(data[0][i]);
data[1] = outputCodes;
b.排序映射:
TreeMap<String, String> mapping = new TreeMap<>();
for(int i = 0; i < data[0].length; i++)
mapping.put(data[0][i], data[1][i]);
data[0] = new String[mapping.size()];
data[1] = new String[mapping.size()];
int index = 0;
for(Map.Entry<String, String> entry : mapping.entrySet()) {
data[0][index] = entry.getKey();
data[1][index] = entry.getValue();
index++;
}
这些方法都有一个缺点,即它们只适用于两列数据。如果您有更多,您的值必须成为自定义对象或对象数组或类似的东西。无论哪种方式,这种方法都相当笨重,我提供它只是为了说明如果您确实愿意的话,如何可以跳过额外的障碍。
可能还有其他方法,但正如#3所示,我怀疑与此处显示的三种方法相比,它们在速度、内存或易读性/可维护性方面不会特别有效。
另请记住,流可以让您更轻松地完成我在此处向您展示的所有操作。
尝试一下。非常适合我。
Map<String, String> unsortMap = new HashMap<>();
unsortMap.put("Columbia", "B216");
unsortMap.put("Chile", "B217");
unsortMap.put("Asia", "A442");
unsortMap.put("US", "N665");
System.out.println("Original...");
System.out.println(unsortMap);
Map<String, String> result = new LinkedHashMap<>();
//sort by key, a,b,c..., and put it into the "result" map
unsortMap.entrySet().stream()
.sorted(Map.Entry.<String, String>comparingByKey())
.forEachOrdered(x -> result.put(x.getKey(), x.getValue()));
System.out.println("Sorted...");
System.out.println(result);
解决方案
采纳 Socowi 和 Stephen P 的建议并同时对多个数组进行排序我想出了以下解决方案
当我将此数据返回到 JSP 以填充下拉菜单时,我为模型添加了一个类,并迭代数组,将模型类的新实例添加到数组列表中
for (int i = 0; i < data[0].length; i++) {
dataList.add(new LocationModel(data[0][i], data[1][i].trim()));
}
模型类实现Comparable并重写compareTo方法
public class LocationModel implements Comparable<LocationModel> {
...
@Override
public int compareTo(LocationModel other) {
return this.locName.compareToIgnoreCase(other.getLocName());
}
}
然后我简单地对数组列表进行排序
Collections.sort(dataList);
这解决了我的问题。
感谢大家的协助
包 com.mycompany.stringsortingby2darray;
公共类 StringSortingby2dArray {
public static void main(String[] args) {
字符串数据[][]= {{"MADHYAPRADESH",String.valueOf(1)},{"BHARAT",String.valueOf(2)},{"美国",String.valueOf(13)},{"澳大利亚",String.valueOf(17)},{"UTTARPRADESH",String.valueOf(5)}};
for (int i = 0; i < data.length; i++) {
//for (int j = 0; j < data.length; j++) {
System.out.println(data[i][0]);
}
}
}