如何实现基于输入参数类型的动态返回类型,编写支持任意类型列表的按键排序通用函数?
要实现这个通用的排序函数,我们可以借助Java的泛型来支持任意类型的待排序列表,同时保证返回的列表类型和输入完全一致。下面分两种方案来实现——一种基于Java原生API,另一种沿用你原来的Guava工具类思路做泛化改造。
方案一:Java原生API实现(无需第三方库)
这个方案不依赖任何第三方工具,完全用Java标准库完成,更轻量化。核心思路是先把键和对应值配对,按键排序后,再将值填入和输入同类型的列表中。
import java.util.*; public class GenericSortUtil { public static <T> List<T> sort(List<Integer> keys, List<T> valuesToSort) { // 先校验两个列表长度一致,避免索引越界 if (keys.size() != valuesToSort.size()) { throw new IllegalArgumentException("Keys and values lists must have the same size"); } // 生成键值对列表,保留原始索引的对应关系 List<Map.Entry<Integer, T>> keyValuePairs = new ArrayList<>(); for (int i = 0; i < keys.size(); i++) { keyValuePairs.add(new AbstractMap.SimpleEntry<>(keys.get(i), valuesToSort.get(i))); } // 按键的自然顺序排序 keyValuePairs.sort(Map.Entry.comparingByKey()); // 创建与输入同类型的列表实例 List<T> sortedValues; try { sortedValues = valuesToSort.getClass().newInstance(); } catch (InstantiationException | IllegalAccessException e) { // 如果无法实例化(比如私有构造),降级使用ArrayList sortedValues = new ArrayList<>(); } // 将排序后的值添加到新列表 for (Map.Entry<Integer, T> pair : keyValuePairs) { sortedValues.add(pair.getValue()); } return sortedValues; } // 测试示例 public static void main(String[] args) { List<Integer> keys = Arrays.asList(3, 5, 2, 4, 1); List<String> valuesToSort = Arrays.asList("A", "B", "C", "D", "E"); List<String> sortedValues = sort(keys, valuesToSort); System.out.println(sortedValues); // 输出 [E, C, A, D, B] // 测试整数列表类型 List<Integer> numValues = Arrays.asList(30, 50, 20, 40, 10); List<Integer> sortedNums = sort(keys, numValues); System.out.println(sortedNums); // 输出 [10, 20, 30, 40, 50] // 测试LinkedList输入,返回同类型列表 LinkedList<Double> doubleValues = new LinkedList<>(Arrays.asList(3.1, 5.2, 2.3, 4.4, 1.5)); LinkedList<Double> sortedDoubles = (LinkedList<Double>) sort(keys, doubleValues); System.out.println(sortedDoubles.getClass().getSimpleName()); // 输出 LinkedList System.out.println(sortedDoubles); // 输出 [1.5, 2.3, 3.1, 4.4, 5.2] } }
关键点说明:
- 用
<T>泛型参数让函数支持任意类型的List<T>输入 - 通过
valuesToSort.getClass().newInstance()尝试创建同类型列表,严格保证返回类型和输入一致;如果实例化失败(比如列表类有私有构造),则降级使用ArrayList - 提前做长度校验,避免运行时出现索引越界错误
方案二:基于Guava的泛化改造(沿用原有思路)
如果你项目中已经依赖Guava,可以把原来的String专属版本改成泛型版本,同时保留返回类型一致性:
import com.google.common.collect.*; import java.util.List; public class GuavaGenericSortUtil { public static <T> List<T> sort(List<Integer> keys, List<T> valuesToSort) { if (keys.size() != valuesToSort.size()) { throw new IllegalArgumentException("Keys and values lists must have the same size"); } Multimap<Integer, T> multiMap = LinkedListMultimap.create(); for (int i = 0; i < keys.size(); i++) { multiMap.put(keys.get(i), valuesToSort.get(i)); } // 创建同类型的列表实例 List<T> sortedValues; try { sortedValues = valuesToSort.getClass().newInstance(); } catch (InstantiationException | IllegalAccessException e) { sortedValues = Lists.newArrayList(); } // 按键的自然顺序遍历,添加对应的值 for (Integer key : Ordering.natural().sortedCopy(multiMap.keys())) { sortedValues.addAll(multiMap.get(key)); } return sortedValues; } // 测试示例 public static void main(String[] args) { List<Integer> keys = Arrays.asList(3, 5, 2, 4, 1); List<String> valuesToSort = Arrays.asList("A", "B", "C", "D", "E"); List<String> sortedValues = sort(keys, valuesToSort); System.out.println(sortedValues); // 输出 [E, C, A, D, B] } }
关键点说明:
- 将原来的
String替换为泛型<T>,让Multimap支持任意类型的值 - 同样处理了返回列表的类型一致性问题,优先复用输入列表的类型
- 保留了你原有的Guava使用逻辑,适合已经依赖Guava的项目
额外注意事项
- 如果
keys中有重复值,两个方案都会保留对应值的原始顺序(LinkedListMultimap和ArrayList的键值对都是按插入顺序保存的),符合稳定排序的预期 - 若需要自定义键的排序逻辑(比如倒序),可以把排序器作为参数传入函数,进一步增强通用性
内容的提问来源于stack exchange,提问作者PebNischl
相关产品推荐
相关产品推荐

