我正在尝试回答this question about parsing data and sorting into bins。我想我几乎已经解决了,但似乎无法让它正常工作。
这是我的代码:
package soBins;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Bins {
public static void main(String[] args) {
String rangeIn = "100 101 3.45\n101 102 4.23\n103 104 2.40\n199 200 6.89";
String dataIn = "xx 108.45\nxx 122.00\nyy 124.78\nxx 156.93\nzz 101.5\nxx 103.5\nzz 101.25";
Scanner rangeScanner = new Scanner(rangeIn);
Scanner dataScanner = new Scanner(dataIn);
ArrayList<Bin> bins = new ArrayList<Bin>();
while (rangeScanner.hasNextLine()) {
String line = rangeScanner.nextLine();
String[] tokens = line.split(" ");
int min = Integer.parseInt(tokens[0]);
int max = Integer.parseInt(tokens[1]);
// System.out.println("Creating new bin, min "+ min + ", max "+ max);
bins.add(new Bin(min,max));
}
Map<String,ArrayList<Bin>> namedBins = new HashMap<String,ArrayList<Bin>>();
while (dataScanner.hasNextLine()) {
String line = dataScanner.nextLine();
String[] tokens = line.split(" ");
String name = tokens[0]; // name is first token on line
float data = Float.parseFloat(tokens[1]); // data is second token on line
if (!namedBins.containsKey(name)) {
// Shouldn't this create a new copy of the ArrayList of bins??
namedBins.put(name, new ArrayList<Bin>(bins));
}
for (Bin b : namedBins.get(name)) {
if (b.isInRange(data)) {
System.out.println("adding "+ data + " to bin in "+ name);
b.addData(data);
}
}
}
System.out.println("All bins and data contents:");
for (String dataName : namedBins.keySet()) { // print all values and bin ranges
for (Bin range : namedBins.get(dataName)) {
System.out.println(dataName + ", min " + range.getMin() + ", max " + range.getMax()
+ ", data is " + range.getData());
}
}
}
}
我的Bin课程:
package soBins;
import java.util.ArrayList;
public class Bin {
int min = 0;
int max = 0;
ArrayList<Float> values = new ArrayList<Float>();
Bin(int min,int max) {
this.min = min;
this.max = max;
}
public boolean isInRange(float data) {
return (min < data) && (data < max);
}
public void addData(float data) {
values.add(data);
}
public int getMin() {
return min;
}
public void setMin(int min) {
this.min = min;
}
public int getMax() {
return max;
}
public void setMax(int max) {
this.max = max;
}
public ArrayList<Float> getData() {
return values;
}
}
输出似乎是将数据添加到每个数据集,而不仅仅是它的意图。
输出结果为:
adding 101.5 to bin in zz
adding 103.5 to bin in xx
adding 101.25 to bin in zz
All bins and data contents:
zz, min 100, max 101, data is []
zz, min 101, max 102, data is [101.5, 101.25]
zz, min 103, max 104, data is [103.5]
zz, min 199, max 200, data is []
yy, min 100, max 101, data is []
yy, min 101, max 102, data is [101.5, 101.25]
yy, min 103, max 104, data is [103.5]
yy, min 199, max 200, data is []
xx, min 100, max 101, data is []
xx, min 101, max 102, data is [101.5, 101.25]
xx, min 103, max 104, data is [103.5]
xx, min 199, max 200, data is []
为什么它会添加到所有组中,而不仅仅是添加到目标组?
答案 0 :(得分:2)
您只需创建一次Bin
个实例,并在初始化地图之前将其放入bins
列表中:
ArrayList<Bin> bins = new ArrayList<Bin>();
while (rangeScanner.hasNextLine()) {
....
bins.add(new Bin(min,max));
}
并使用相同的bins
实例初始化Map的所有键的值:
namedBins.put(name, new ArrayList<Bin>(bins));
虽然此语句为每个ArrayList
条目创建一个新的Map
,但它会从原始Bin
列表中添加相同的bins
个实例。
这意味着Map中每个Bin
列表中的Bin
个实例都是相同的,因此当您修改这些Bin
个实例时,您将更改所有Map
条目。
为了在每个Bin
条目中拥有唯一的Map
个实例,您必须在Bin
类中拥有复制构造函数或克隆方法。然后你会做这样的事情:
if (!namedBins.containsKey(name)) {
List<Bin> newBins = new ArrayList<Bin>();
newdBins.put(name, new newBins);
for (Bin bin : bins)
newBins.add (new Bin(bin)); // using a copy constructor
}