【发布时间】:2017-06-12 13:44:29
【问题描述】:
我喜欢检查 Excel .csv 列,该列可能是 String、Int oder Double 类型。我实现了一个经典的泛型 Pair 类:
public class PairT<K,V> implements Comparable<PairT<K,V>>
如果是整数列,列值存储在:
ArrayList<PairT<Integer,Integer>> column_list = new ArrayList<>();
V 值保存 excel 行索引的位置。
下面的代码 sn-p 显示了令人讨厌的解决方案 - 我会改进:
// Add a cell value of type T to the column list
@SuppressWarnings("unchecked")
public static <T> void addCell(
String excelcell,
int row_idx,
boolean ignorecase,
T defkey,
/*IO*/ArrayList<PairT<T,Integer>> column_list) throws RuntimeException
{
//Class<?> classtype = defkey.getClass(); String typename = classtype.getSimpleName();
char type;
if (defkey instanceof String) type = 'S';
else if (defkey instanceof Integer) type = 'I';
else if (defkey instanceof Double) type = 'D';
else type = 'O'; // other
T key;
try
{
switch(type)
{
case 'I':
try
{ key = (T)new Integer(excelcell);
} catch (NumberFormatException e) { key = defkey; }
column_list.add(new PairT<T,Integer>(key,row_idx));
break;
case 'D':
try
{ key = (T)new Double(excelcell);
} catch (NumberFormatException e) { key = defkey; }
column_list.add(new PairT<T,Integer>(key,row_idx));
break;
case 'S':
if (ignorecase) excelcell = excelcell.toUpperCase();
column_list.add(new PairT<T,Integer>((T)excelcell,row_idx));
break;
default: // Other take the .toString() output as key
column_list.add(new PairT<T,Integer>((T)excelcell.toString(),row_idx));
}
}catch (Exception ex) // possibly a ClassCastException
{
throw new RuntimeException("addCell(): Problems using PairT<K,V>",ex);
}
} //----- end of addCell()
为了测试我使用:
ArrayList<PairT<Integer,Integer>> column_list = new ArrayList<>();
int row_idx = 0;
boolean ic = true; // for String values only;
Integer defval = new Integer("0");
String cell = "12";
addCell(cell,row_idx,ic,defval,column_list);
cell = "17.34"; // leads to def val
addCell(cell,++row_idx,ic,defval,column_list);
cell = "456";
addCell(cell,++row_idx,ic,defval,column_list);
cell = "foo"; // lead to def avlue
addCell(cell,++row_idx,ic,defval,column_list);
System.out.println("result: " + column_list);
// [12;0, 0;1, 456;2, 0;3]
java.util.Collections.sort(column_list);
System.out.println("Sorted: " + column_list);
//Sorted: [0;1, 0;3, 12;0, 456;2]
它按预期工作,但是 - 正如我所说 - 我不想区分 addCell() 中的 Type T。 我更喜欢简短的解决方案,例如:
if (ignorecase) column_list.add(new PairT<T,Integer>((T)excelcell.toUpperCase(),row_idx));
else column_list.add(new PairT<T,Integer>((T)excelcell,row_idx));
【问题讨论】:
-
仅供参考,K 和 V 作为映射中的类型代表键和值。它们不是配对类中真正合适的标识符,因为没有键或值。
-
你应该可以逃脱钻石运算符:
list.add(new PairT<>(foo,foo)) -
默认的 switch case 通过将
String转换为T导致堆污染。你应该扔例如IllegalArgumentException代替。 -
我能想到的最简洁的解决方案是创建三个独立的
addCell方法,分别使用Integer defKey、Double defKey和String defKey参数。这使您可以完全取消T,这应该会大大简化代码。