为什么在我的代码中使用Apache POI后结果会立即更改?

时间:2019-01-10 15:47:51

标签: java excel apache-poi

我在代码中将问题缩小到了这一行: “工作簿工作簿=新的HSSFWorkbook();” 一旦我注释掉这一行并使用System.out语句直接打印结果,所有结果都很好。

我什至尝试使用XSSFWorkbook,问题依然存在。 然后我以为我的外部库有问题,而DOUBLE是造成问题的原因。我尝试将内部HashMap值类型更改为Double(来自Java),但仍然无法正常工作。

编辑:我也尝试过删除此处未显示的代码,而只运行此处显示的代码。问题仍然存在。

public static void main(String[] args) throws Exception {
HashMap<SET<Integer>, HashMap<String,DOUBLE>> Qvalues= 
bb.MSQATVHM();
Workbook workbook = new HSSFWorkbook();
for(SET<Integer> IntegerSet:Qvalues.keySet()){
    System.out.println(IntegerSet);
    System.out.println(Qvalues.get(IntegerSet));
    }
// Program continues.....the rest doesn't matter here.
}

预期:[1733]

{Value1 = 0.0657304324073498,Value2 = 21213.0,Value3 = 18.57715885746071,Value4 = 0.33081495617910694}

实际:[1733]

{Value1 = 0.0394381995860269,Value2 = 12727.800000000001,Value3 = 11.14629515620783,Value4 = 0.35655228866335265}

1 个答案:

答案 0 :(得分:0)

仅表明您的假设是错误的:

完整示例:

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.util.*;

public class UsingPOITest  {
 public static void main(String[] args) throws Exception {

  HashMap<Set<Integer>, HashMap<String, Double>> Qvalues = new HashMap<Set<Integer>, HashMap<String, Double>>();
  Set<Integer> set = new HashSet<Integer>();
  set.add(new Integer(1733));
  HashMap<String, Double> hashMap = new HashMap<String, Double>();
  hashMap.put("Value1", new Double(0.0657304324073498));
  hashMap.put("Value2", new Double(21213.0));
  hashMap.put("Value3", new Double(18.57715885746071));
  hashMap.put("Value4", new Double(0.33081495617910694));
  Qvalues.put(set, hashMap);
  Workbook workbook = null;
  //workbook = new HSSFWorkbook();
  System.out.println("Workbook: " + workbook);
  for(Set<Integer> IntegerSet : Qvalues.keySet()){
   System.out.println(IntegerSet);
   System.out.println(Qvalues.get(IntegerSet));
  }
 }
}

未创建HSSFWorkbook的结果:

axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ java -cp .:./*:./lib/*:./ooxml-lib/* UsingPOITest 
Workbook: null
[1733]
{Value3=18.57715885746071, Value4=0.33081495617910694, Value1=0.0657304324073498, Value2=21213.0}

创建HSSFWorkbook的结果:

axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ java -cp .:./*:./lib/*:./ooxml-lib/* UsingPOITest 
Workbook: org.apache.poi.hssf.usermodel.HSSFWorkbook@573fd745
[1733]
{Value3=18.57715885746071, Value4=0.33081495617910694, Value1=0.0657304324073498, Value2=21213.0}

如果返回bb的{​​{1}}在单独的线程中运行,并且正在不断更新HashMap<Set<Integer>, HashMap<String, Double>> Qvalues,我可以重现该问题。然后,创建工作簿只是问题,因为它需要一段时间才能重新更新MSQATVHM

示例:

MSQATVHM

结果:

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.util.*;

public class UsingPOITest  {
 public static void main(String[] args) throws Exception {

  BB bb = new BB();
  bb.start();
  Thread.sleep(1000);

  HashMap<Set<Integer>, HashMap<String, Double>> Qvalues = bb.MSQATVHM();
  System.out.println(Qvalues);

  Thread.sleep(1000);

  for(Set<Integer> IntegerSet : Qvalues.keySet()){
   System.out.println(IntegerSet);
   System.out.println(Qvalues.get(IntegerSet));
  }
 }

 static class BB extends Thread {

  HashMap<Set<Integer>, HashMap<String, Double>> msQatVHM = new HashMap<Set<Integer>, HashMap<String, Double>>();

  void setMSQatVHM(int atVHM) {
   msQatVHM.clear();
   Set<Integer> set = new HashSet<Integer>();
   set.add(new Integer(1733));
   HashMap<String, Double> hashMap = new HashMap<String, Double>();
   if (atVHM == 0) { 
    hashMap.put("Value1", new Double(0.0657304324073498));
    hashMap.put("Value2", new Double(21213.0));
    hashMap.put("Value3", new Double(18.57715885746071));
    hashMap.put("Value4", new Double(0.33081495617910694));
   } else {
    hashMap.put("Value1", new Double(0.0394381995860269));
    hashMap.put("Value2", new Double(12727.800000000001));
    hashMap.put("Value3", new Double(11.14629515620783));
    hashMap.put("Value4", new Double(0.35655228866335265));
   }
   msQatVHM.put(set, hashMap);
  }

  HashMap<Set<Integer>, HashMap<String,Double>> MSQATVHM() {
   return msQatVHM;
  }

  public void run() {
   setMSQatVHM(0);
   try {
    this.sleep(1000);
   } catch (Exception ex) {
    ex.printStackTrace();
   }
   setMSQatVHM(1);
  }
 }

}

免责声明: 上面的代码旨在显示问题,正如我在此处的所有代码示例一样,并非旨在准备进行生产性使用。

最后一个代码部分显示了多线程的滥用。 axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ javac -Xlint:deprecation -Xlint:unchecked -cp .:./*:./lib/*:./ooxml-lib/* UsingPOITest.java axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ java -cp .:./*:./lib/*:./ooxml-lib/* UsingPOITest {[1733]={Value3=18.57715885746071, Value4=0.33081495617910694, Value1=0.0657304324073498, Value2=21213.0}} [1733] {Value3=11.14629515620783, Value4=0.35655228866335265, Value1=0.0394381995860269, Value2=12727.800000000001} 不是线程安全的,因此当另一个线程尝试获取它们时,甚至可能是该映射中的单个项目尚未准备就绪。

问题代码中的变量名也部分地被我的代码所接管,尽管它们违反了HashMap命名约定。出于可比较性而完成此操作。我知道变量不应命名为Java,而应以小写的Qvalues-qValues命名。而且,永远不要将方法命名为camleCaseStyle,因为大写名称只能是常量名称。