- 浏览: 79378 次
文章分类
最新评论
-
wodentt:
....为什么楼主都英文的博客
用java解决百度之星移动火柴的问题 part 1 -
wensonzhou86:
思路明确,代码清晰,通俗易懂
visit 淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和 -
carydeepbreathing:
代码比较干净
visit 淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和 -
meiowei:
yangguo 写道i don't think it is a ...
用java解决百度之星移动火柴的问题 part 2 -
yangguo:
i don't think it is a good way ...
用java解决百度之星移动火柴的问题 part 2
Though, as I wrote before, it's very hard to come up a universal dynamic data structure to fit all needs, sometimes we still need a somewhat general dynamic data structure due to requirements. For example, the spreadsheet could have as many columns during runtime, we can't determine the number of columns during compile time.
I have a very bad example of an implementation at work, it has some 3000 lines of code. I think it's for me to think about how it ends up like this and what are the better alternatives. Another motivation is still from the blog, I want to see how close I can get to ultimate - universal dynamic data structure, though I don't believe we can reach there. But the old saying says, you can't reach the North Star, but it always points to the right direction.
So here is my journey.
It's a data matrix, it has headers that we call fields, it has rows and columns. Each column has same data type. This class is going across wires as well. And it has 3000 lines, for God's sake.
After consolidate method signatures, The new class is like this
I am not surprised to see that the only dependency on the headers is just an empty interface, as a flag.
If you compare the Swing's TableModel implementations to this one, it's almost the same, except the event handling portion, plus we have several extra methods. This is a good sign that we abstract the responsibility at the right level, not too many responsibilities.
The only relevant missing piece is the serialization. We can either implements Serializable or Externalizable.
In this implementation, I delegate the dynamic memory allocation to Collection classes. I could use a Map that maps fields to columns, but I instead use two Lists for speeding.
I also supplied a toString() method for debugging purpose, but left out other formatters, like toXml(), toCvs() etc.
Since this is more of a design issue, I left out most of the code untested. For simple testing, I created a simple field class:
A real world Field class would have dependencies on date, currency and other factors.
I have a very bad example of an implementation at work, it has some 3000 lines of code. I think it's for me to think about how it ends up like this and what are the better alternatives. Another motivation is still from the blog, I want to see how close I can get to ultimate - universal dynamic data structure, though I don't believe we can reach there. But the old saying says, you can't reach the North Star, but it always points to the right direction.
So here is my journey.
It's a data matrix, it has headers that we call fields, it has rows and columns. Each column has same data type. This class is going across wires as well. And it has 3000 lines, for God's sake.
- stripped out the code for memory allocation, replace them with Collection classes
- stripped out the type meta data, removed all the type-safe getters/setters, they should be on the caller side, the meta data should be in the headers
- stripped out the methods related to cell/row/column computations. This should be a dedicated class later on since the same kind of logic spreads in a few places.
- stripped out the toXml() and other output methods.
After consolidate method signatures, The new class is like this
java 代码
- import java.util.List;
- import java.util.Map;
- import java.util.ArrayList;
- import java.util.HashMap;
- /**
- * A Data matrix class, mainly for weak typed data, e.g., a table in swing.
- * Implementation reference, TableModel, DefaultTableModel.
- *
- * Note that the header type Field is really used as a flag, except the
- * hashcode used in the Map class.
- */
- public class DataMatrix
- {
- private List columns; // column values
- private List fields; // field values, order is significant.
- private Map fieldToColumns; // what to do with duplicated fields.
- public DataMatrix()
- {
- fields = new ArrayList();
- columns = new ArrayList();
- fieldToColumns = new HashMap();
- }
- public DataMatrix(List fields)
- {
- this.fields = new ArrayList(fields);
- columns = new ArrayList(fields.size());
- fieldToColumns = new HashMap(fields.size());
- }
- public DataMatrix(DataMatrix dataMatrix)
- {
- this.columns = new ArrayList(dataMatrix.columns);
- this.fields = new ArrayList(dataMatrix.fields);
- this.fieldToColumns = new HashMap(dataMatrix.fieldToColumns);
- }
- //-----------------------------------------------------------------------
- // field operations
- //-----------------------------------------------------------------------
- public List getColumnFields() { return fields; }
- public void setColumnFields(List fields) { this.fields = new ArrayList(fields); }
- public Field getField(int col) { return (Field)fields.get(col); }
- public int getColumnNumber(Field field)
- {
- Integer index = (Integer)fieldToColumns.get(field);
- // should throw a cumstomized exception
- if (index == null) throw new IllegalArgumentException("field not found: " + field.toString());
- return index.intValue();
- }
- //-----------------------------------------------------------------------
- // column operations
- //-----------------------------------------------------------------------
- public int getNumberOfColumns() { return columns.size(); }
- public List getColumn(int col) { return (List) columns.get(col); }
- public List getColumn(Field key)
- {
- return (List) columns.get(getColumnNumber(key));
- }
- public void addColumn(Field field, List column)
- {
- checkNullAndEqualSize(field, column);
- fieldToColumns.put(field, new Integer(fields.size()));
- fields.add(field);
- columns.add(new ArrayList(column));
- }
- public void insertColumn(int position, Field field, List column)
- {
- checkNullAndEqualSize(field, column);
- fieldToColumns.put(field, new Integer(position));
- fields.add(position, field);
- columns.add(position, column);
- }
- private void checkNullAndEqualSize(Field field, List column)
- {
- if (field == null) throw new IllegalArgumentException("field is null");
- if (column == null) throw new IllegalArgumentException("column is null");
- if (columns.size() > 0)
- {
- List existingRow = (List)columns.get(0);
- if (existingRow.size() != column.size())
- {
- throw new IllegalArgumentException("column size doesn't match: "
- + " existing column size=" + existingRow.size()
- + " to be added column size=" + column.size());
- }
- }
- }
- public void deleteColumn(int position)
- {
- fieldToColumns.remove(fields.get(position));
- fields.remove(position);
- columns.remove(position);
- }
- public void deleteColumn(Field field)
- {
- Integer index = (Integer)fieldToColumns.get(field);
- if (index == null) return; // no such field here, do nothing
- fieldToColumns.remove(field);
- fields.remove(index.intValue());
- columns.remove(index.intValue());
- }
- // reorder the data matrix with the given fields.
- // if there is extra fields, throws exception
- public void reorder(Field[] fieldsInNewOrder)
- {
- // check fields to see whether they are the same.
- List newFields = new ArrayList();
- List newColumns = new ArrayList();
- Map newFieldToColumns = new HashMap();
- for (int i=0; i
- {
- newFields.add(fieldsInNewOrder[i]);
- int index = ((Integer)fieldToColumns.get(fieldsInNewOrder[i])).intValue();
- newColumns.add(columns.get(index));
- newFieldToColumns.put(fieldsInNewOrder, new Integer(i));
- }
- this.fields = newFields;
- this.columns = newColumns;
- this.fieldToColumns = newFieldToColumns;
- }
- //-----------------------------------------------------------------------
- // row operations
- //-----------------------------------------------------------------------
- public int getNumberOfRows()
- {
- if (columns.size() == 0) return 0;
- List firstColumn = (List)columns.get(0);
- return firstColumn.size(); // should optimize this - trade speed with space.
- }
- public List getRow(int row)
- {
- List ret = new ArrayList();
- for (int i=0; i
- {
- List columnList = (List) columns.get(i);
- ret.add(columnList.get(row));
- }
- return ret;
- }
- public void addRow(List row)
- {
- checkSizeMatch(row);
- for (int i=0; i
- {
- List columnList = getExistingOrNewColumn(i);
- columnList.add(row.get(i));
- }
- }
- public void insertRow(int position, List row)
- {
- checkSizeMatch(row);
- for (int i=0; i
- {
- List columnList = getExistingOrNewColumn(i);
- columnList.add(position, row.get(i));
- }
- }
- private void checkSizeMatch(List row)
- {
- if (row == null)
- {
- throw new IllegalArgumentException("row is null");
- }
- if (fields.size() == 0)
- {
- throw new IllegalStateException("set the fields before adding rows");
- }
- // not empty and not equals
- if (columns.size() != 0 && row.size() != columns.size())
- {
- throw new IllegalArgumentException("mismatched column size: " +
- "datamatrix num of columns=" + columns.size() + " to be "
- + "added row size=" + row.size());
- }
- }
- private List getExistingOrNewColumn(int i)
- {
- List columnList;
- if (i >= columns.size()) // empty columns
- {
- columnList = new ArrayList();
- columns.add(columnList);
- }
- else // existing
- {
- columnList = (List) columns.get(i);
- }
- return columnList;
- }
- // normal, in a data matrix, we need to loop from n-1 to 0
- // in order to use this in a loop.
- public void deleteRow(int rowNumber)
- {
- for (int i=0; i
- {
- List columnList = (List) columns.get(i);
- columnList.remove(rowNumber);
- }
- }
- //-----------------------------------------------------------------------
- // element operations
- //-----------------------------------------------------------------------
- // before you call these two methods, make sure you do populate the data.
- // Otherwise you will get an IndexOutOfBoundsException.
- public void setCellValueAt(int row, int col, Object value)
- {
- if (col >= columns.size())
- {
- throw new IllegalArgumentException("try to set value at an uninitialized cell");
- }
- ((List)columns.get(col)).set(row, value);
- }
- public Object getCellValue(int row, int col)
- {
- if (col >= columns.size())
- {
- throw new IllegalArgumentException("try to get value at an uninitialized cell");
- }
- List column = (List)columns.get(col);
- if (column == null || row >= column.size())
- {
- throw new IllegalArgumentException("try to get value at an uninitialized cell");
- }
- return ((List)columns.get(col)).get(row);
- }
- //-----------------------------------------------------------------------
- // matrix operations
- //-----------------------------------------------------------------------
- // append rows at the bottom
- public void concatenateRows(DataMatrix dataMatrix)
- {
- // check same number of columns first.
- if (columns.size() != dataMatrix.getNumberOfColumns())
- {
- throw new IllegalArgumentException("Two matrices have different "
- + "number of columns: " + columns.size() + " != " +
- dataMatrix.getNumberOfColumns());
- }
- for (int j=0; j
- {
- ((List)columns.get(j)).addAll(dataMatrix.getColumn(j));
- }
- }
- // append columns at the right end
- public void concatenateColumns(DataMatrix dataMatrix)
- {
- // check both matrices have the same number of rows.
- if (this.getNumberOfRows() != dataMatrix.getNumberOfRows())
- {
- throw new IllegalArgumentException("Two matrices have different "
- + "number of rows: " + getNumberOfRows() + " != " +
- dataMatrix.getNumberOfRows());
- }
- int startCol = columns.size();
- for (int j=0; j
- {
- fieldToColumns.put(dataMatrix.getField(j), new Integer(j + startCol));
- fields.add(dataMatrix.getField(j));
- columns.add(dataMatrix.getColumn(j));
- }
- }
- // split the datamatrix to two which are the two sides of this field.
- // The specified field could be on the right/left/not included.
- public DataMatrix[] splitFrom(Field field)
- {
- int colNum = getColumnNumber(field);
- DataMatrix leftMatrix = new DataMatrix();
- DataMatrix rightMatrix = new DataMatrix();
- for (int i=0; i
- {
- leftMatrix.addColumn((Field)fields.get(i), (List)columns.get(i));
- }
- for (int i=colNum; i
- {
- rightMatrix.addColumn((Field)fields.get(i), (List)columns.get(i));
- }
- return new DataMatrix[] {leftMatrix, rightMatrix};
- }
- public String toString()
- {
- String ret = "";
- if (fields == null) return ret;
- // output fields first
- for (int i=0; i
- {
- ret += fields.get(i).toString() + " | ";
- }
- ret += "\n";
- if (columns == null) return ret;
- // output rows
- for (int i=0; i
- {
- for (int j=0; j
- {
- ret += ((List)columns.get(j)).get(i).toString() + " | ";
- }
- ret += "\n";
- }
- return ret;
- }
I am not surprised to see that the only dependency on the headers is just an empty interface, as a flag.
java 代码
- public interface Field
- {
- }
If you compare the Swing's TableModel implementations to this one, it's almost the same, except the event handling portion, plus we have several extra methods. This is a good sign that we abstract the responsibility at the right level, not too many responsibilities.
The only relevant missing piece is the serialization. We can either implements Serializable or Externalizable.
In this implementation, I delegate the dynamic memory allocation to Collection classes. I could use a Map that maps fields to columns, but I instead use two Lists for speeding.
I also supplied a toString() method for debugging purpose, but left out other formatters, like toXml(), toCvs() etc.
Since this is more of a design issue, I left out most of the code untested. For simple testing, I created a simple field class:
java 代码
- public class StringField implements Field
- {
- private String name;
- public StringField(String name)
- {
- this.name = name;
- }
- public String getName() { return name; }
- public boolean equals(Object obj)
- {
- if (!(obj instanceof StringField)) return false;
- StringField field = (StringField)obj;
- return this.name.equals(field.name);
- }
- public int hashCode() { return name.hashCode(); }
- public String toString() { return getName(); }
- }
A real world Field class would have dependencies on date, currency and other factors.
发表评论
-
Rich Domain Model 2
2007-04-05 04:02 66Problems: 1. If the DAO featur ... -
Heavyweight domain objects vs lightweight domain objects
2007-03-20 03:55 36Sometimes, domain objects could ... -
Rich Domain Model
2007-03-04 12:44 1064The discussion started with Mar ... -
OOP
2007-04-13 00:53 1132OCP: Open for extension, close ... -
The boundary between application layer and system layer
2007-02-23 07:06 34We all want to reuse code. But ... -
A data matrix implementation 2
2007-02-12 23:17 1291We could add more functionaliti ... -
Proper abstraction level makes difference.
2007-02-12 23:47 1085Programming is an art, the same ... -
Data abstraction - universal/dynamic data structure
2007-02-09 04:37 1110Recently, I read two articles a ...
相关推荐
DataMatrix 二维码生成 和解码 C#程序,亲测可用。解码是Freytag DataMatrixDecoder A c# implementation to find DataMatrix 'barcodes' in bitmaps and decode them back into a string.
在本文中,我们将重点讨论如何使用ZXing库在Android平台上生成DataMatrix类型的点阵二维码,并解决可能出现的问题,如生成长条点阵图或图片过小。 ZXing(Zebra Crossing)是一个开源的、跨平台的条码读取和生成库...
1)x: your data matrix samples in rows and variables in columns. 2)LV: How many variables to use from data, if not specified all variables are used. 3)method: Optional, will be selected automatically. ...
cov_matrix = cov(data); ``` 3. **特征值分解**:协方差矩阵是一个实对称矩阵,因此可以进行特征值分解。这一步骤将帮助我们找出主成分的方向。MATLAB中的`eig`函数可以完成这个任务。 ```matlab [~, ...
Offered as an introduction to the field of data structures and algorithms, Open Data Structures covers the implementation and analysis of data structures for sequences (lists), queues, priority queues...
with simulated and experimental data for a range of denoising and sparse-sampling applications. LORAKS is also compared against state-of-the-art methods like homodyne reconstruction, `1-norm ...
In the conventional GMM-UBM framework the universal background model (UBM) is a Gaussian mixture model (GMM) that is trained on a pool of data (known as the background or development data) from a ...
The **lock-compatibility matrix** plays a key role here, determining whether a transaction can be granted a lock based on the locks already held by other transactions on the same item. Multiple ...
1. **添加依赖**:在项目的`build.gradle`文件中,添加ZXing的依赖库。如果是使用Gradle,可以添加如下依赖: ```groovy implementation 'com.google.zxing:core:3.4.1' implementation '...
A matlab function libsvmwrite writes Matlab matrix to a file in LIBSVM format: libsvmwrite('data.txt', label_vector, instance_matrix] The instance_matrix must be a sparse matrix. (type must be ...
- **2.7–1 A Student Database**: This example illustrates the creation and management of a student database, showcasing data management techniques and skills necessary for developing software ...
“A Large-Scale Benchmark Data Set for Evaluating Pansharpening Performance Overview and implementation”两篇论文提供了评估高光谱和多光谱图像融合(即 pansharpening)性能的大规模基准数据集,这对于比较...
1. The first program calculates the sum of an array of integers using a for loop. 2. The second program prints the elements of a 2D array in a specific order. 3. The third program finds the maximum ...
例如,可以定义一个名为`Matrix`的类,包含私有字段`rows`、`cols`和`data`,分别表示行数、列数和二维数组数据: ```csharp public class Matrix { private int rows; private int cols; private double[,] ...
- Uses a 2D array `a` to represent the adjacency matrix of the graph. - Initializes the `AlGraph` structure `G`. - **Edge Construction:** - For each vertex `i`, creates an adjacency list by adding ...
- Use of 'areas' data matrix is now optional. - Many new tests in test suite. * Bugs fixed: - Branch power flow limits could be violated when using the option OPF_FLOW_LIM = 1. * ...
the data obtained with the existing data, it is concluded that the opening of the second child has a positive effect on China’s economic development, the alleviation of aging, and the increase in the...
Populating a DataSet Class with a Data Adapter 722 Populating a DataSet from XML 723 xx Contents Persisting DataSet Changes 723 Updating with Data Adapters 724 Writing XML Output 726 Working with ADO...