All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.util.collection.AbstractSparseMatrix Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.util.collection;

import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.hfg.util.CompareUtil;
import com.hfg.util.StringUtil;


//------------------------------------------------------------------------------
/**
 Base matrix class.
 
@author J. Alex Taylor, hairyfatguy.com
*/ //------------------------------------------------------------------------------ // com.hfg Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public abstract class AbstractSparseMatrix implements Cloneable { private OrderedSet mOrderedRowKeySet = new OrderedSet<>(); private OrderedSet mOrderedColKeySet = new OrderedSet<>(); private Map> mMatrixMap = new HashMap<>(); private int mInitialColCapacity = sDefaultInitialCapacity; private static int sDefaultInitialCapacity = 99; //########################################################################## // CONSTRUCTORS //########################################################################## //-------------------------------------------------------------------------- public AbstractSparseMatrix() { this(sDefaultInitialCapacity, sDefaultInitialCapacity); } //-------------------------------------------------------------------------- public AbstractSparseMatrix(int inInitialRowCapacity, int inInitialColCapacity) { mOrderedRowKeySet = new OrderedSet<>(inInitialRowCapacity); mOrderedColKeySet = new OrderedSet<>(inInitialRowCapacity); mMatrixMap = new HashMap<>(inInitialRowCapacity); mInitialColCapacity = inInitialColCapacity; } //########################################################################## // PUBLIC METHODS //########################################################################## //-------------------------------------------------------------------------- public void addRow(RK inRowKey) { mOrderedRowKeySet.add(inRowKey); } //-------------------------------------------------------------------------- public void addCol(CK inColKey) { mOrderedColKeySet.add(inColKey); } //-------------------------------------------------------------------------- public void put(RK inRowKey, CK inColKey, V inValue) { mOrderedRowKeySet.add(inRowKey); mOrderedColKeySet.add(inColKey); Map colMap = mMatrixMap.get(inRowKey); if (null == colMap) { colMap = new HashMap<>(mInitialColCapacity); mMatrixMap.put(inRowKey, colMap); } colMap.put(inColKey, inValue); } //-------------------------------------------------------------------------- public void putRow(RK inRowKey, Map inColMap) { if (CollectionUtil.hasValues(inColMap)) { for (CK colKey : inColMap.keySet()) { put(inRowKey, colKey, inColMap.get(colKey)); } } } //-------------------------------------------------------------------------- public void putCol(CK inColKey, Map inRowMap) { if (CollectionUtil.hasValues(inRowMap)) { for (RK rowKey : inRowMap.keySet()) { put(rowKey, inColKey, inRowMap.get(rowKey)); } } } //-------------------------------------------------------------------------- public V get(RK inRowKey, CK inColKey) { V value = null; Map colMap = mMatrixMap.get(inRowKey); if (colMap != null) { value = colMap.get(inColKey); } return value; } //-------------------------------------------------------------------------- public V remove(RK inRowKey, CK inColKey) { V removedValue = null; Map colMap = mMatrixMap.get(inRowKey); if (colMap != null) { removedValue = colMap.remove(inColKey); } return removedValue; } //-------------------------------------------------------------------------- public void clearRow(RK inRowKey) { if (containsRow(inRowKey)) { for (CK colKey : colKeySet()) { remove(inRowKey, colKey); } } } //-------------------------------------------------------------------------- public void clearCol(CK inColKey) { if (containsCol(inColKey)) { for (RK rowKey : rowKeySet()) { remove(rowKey, inColKey); } } } //-------------------------------------------------------------------------- @Override public AbstractSparseMatrix clone() { AbstractSparseMatrix clone; try { clone = (AbstractSparseMatrix) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } clone.mOrderedRowKeySet = new OrderedSet<>(mOrderedRowKeySet); clone.mOrderedColKeySet = new OrderedSet<>(mOrderedColKeySet); clone.mMatrixMap = new HashMap<>(mMatrixMap.size()); for (RK rowKey : mMatrixMap.keySet()) { Map colMap = mMatrixMap.get(rowKey); if (colMap != null) { Map clonedColMap = new HashMap<>(colMap.size()); for (CK colKey : colMap.keySet()) { clonedColMap.put(colKey, colMap.get(colKey)); } clone.mMatrixMap.put(rowKey, clonedColMap); } else { clone.mMatrixMap.put(rowKey, null); } } return clone; } //-------------------------------------------------------------------------- public int size() { int size = 0; for (Map colMap : mMatrixMap.values()) { if (colMap != null) { size += colMap.size(); } } return size; } //-------------------------------------------------------------------------- public MatrixCell getCellWithSmallestValue() { return getCellWithSmallestValue(true); } //-------------------------------------------------------------------------- public MatrixCell getNonIdentityCellWithSmallestValue() { return getCellWithSmallestValue(false); } //-------------------------------------------------------------------------- @Override public String toString() { String outString; try { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); toString(outStream); outStream.close(); outString = outStream.toString(); } catch (IOException e) { throw new RuntimeException(e); } return outString; } //-------------------------------------------------------------------------- public void toString(OutputStream inStream) throws IOException { Writer writer = new PrintWriter(inStream); int maxRowKeyLength = getMaxRowKeyLength(); writer.write(StringUtil.polyChar(' ', maxRowKeyLength) + " "); for (CK colKey : colKeySet()) { writer.write(String.format("%s ", colKey.toString())); } writer.write("\n"); for (RK rowKey : rowKeySet()) { writer.write(String.format("%" + maxRowKeyLength + "." + maxRowKeyLength + "s ", rowKey.toString())); for (CK colKey : colKeySet()) { int colKeyLength = colKey.toString().length(); V value = get(rowKey, colKey); if (value != null) { String stringValue; if (value instanceof Double || value instanceof Float) { stringValue = String.format("%.2f", value); } else { stringValue = value.toString(); } writer.write(String.format("%" + colKeyLength + "." + colKeyLength + "s ", stringValue)); } else { writer.write(StringUtil.polyChar(' ', colKeyLength) + " "); } } writer.write("\n"); } writer.flush(); } //########################################################################## // PROTECTED METHODS //########################################################################## //-------------------------------------------------------------------------- protected Set rowKeySet() { return Collections.unmodifiableSet(mOrderedRowKeySet); } //-------------------------------------------------------------------------- protected boolean containsRow(RK inRowKey) { return mOrderedRowKeySet.contains(inRowKey); } //-------------------------------------------------------------------------- protected Map removeRow(RK inRowKey) { mOrderedRowKeySet.remove(inRowKey); return mMatrixMap.remove(inRowKey); } //-------------------------------------------------------------------------- /** Changes the rowkey inOldKey to inNewKey. */ protected void changeRowKey(RK inOldKey, RK inNewKey) { int index = mOrderedRowKeySet.indexOf(inOldKey); if (index >= 0) { mOrderedRowKeySet.remove(inOldKey); mOrderedRowKeySet.add(index, inNewKey); mMatrixMap.put(inNewKey, mMatrixMap.remove(inOldKey)); } } //-------------------------------------------------------------------------- protected Set colKeySet() { return Collections.unmodifiableSet(mOrderedColKeySet); } //-------------------------------------------------------------------------- protected Map getRow(RK inRowKey) { Map colMap = mMatrixMap.get(inRowKey); return (colMap != null ? Collections.unmodifiableMap(colMap) : null); } //-------------------------------------------------------------------------- protected Map getCol(CK inColKey) { Map rowMap = new OrderedMap<>(rowKeySet().size()); for (RK rowKey : rowKeySet()) { rowMap.put(rowKey, mMatrixMap.get(rowKey).get(inColKey)); } return rowMap; } //-------------------------------------------------------------------------- protected boolean containsCol(CK inColKey) { return mOrderedColKeySet.contains(inColKey); } //-------------------------------------------------------------------------- protected void removeCol(CK inColKey) { if (mOrderedColKeySet.remove(inColKey)) { for (Map colMap : mMatrixMap.values()) { colMap.remove(inColKey); } } } //-------------------------------------------------------------------------- protected void removeCols(Set inColKeys) { if (inColKeys != null && mOrderedColKeySet.removeAll(inColKeys)) { for (Map colMap : mMatrixMap.values()) { for (CK colKey : inColKeys) { colMap.remove(colKey); } } } } //-------------------------------------------------------------------------- /** Changes the colkey inOldKey to inNewKey. */ protected void changeColKey(CK inOldKey, CK inNewKey) { int index = mOrderedColKeySet.indexOf(inOldKey); if (index >= 0) { mOrderedColKeySet.remove(inOldKey); mOrderedColKeySet.add(index, inNewKey); for (RK rowKey : mMatrixMap.keySet()) { Map colMap = mMatrixMap.get(rowKey); if (colMap != null) { if (colMap.containsKey(inOldKey)) { colMap.put(inNewKey, colMap.remove(inOldKey)); } } } } } //-------------------------------------------------------------------------- private int getMaxRowKeyLength() { int maxLength = 0; if (CollectionUtil.hasValues(mOrderedRowKeySet)) { for (RK key : mOrderedRowKeySet) { if (key != null) { int keyLength = key.toString().length(); if (keyLength > maxLength) { maxLength = keyLength; } } } } return maxLength; } //-------------------------------------------------------------------------- private int getMaxColKeyLength() { int maxLength = 0; if (CollectionUtil.hasValues(mOrderedColKeySet)) { for (CK key : mOrderedColKeySet) { if (key != null) { int keyLength = key.toString().length(); if (keyLength > maxLength) { maxLength = keyLength; } } } } return maxLength; } //-------------------------------------------------------------------------- private MatrixCell getCellWithSmallestValue(boolean inIncludeIdentityCells) { V smallestValue = null; RK targetRow = null; CK targetCol = null; for (RK rowKey : mMatrixMap.keySet()) { Map colMap = mMatrixMap.get(rowKey); if (colMap != null) { for (CK colKey : colMap.keySet()) { if (inIncludeIdentityCells || ! rowKey.equals(colKey)) { V value = colMap.get(colKey); if (value != null) { int comparison = 0; if (null == smallestValue) { comparison = 1; } else { comparison = CompareUtil.compare(smallestValue, value); if (0 == comparison) { comparison = CompareUtil.compare(targetCol.toString(), colKey.toString()); } if (0 == comparison) { comparison = CompareUtil.compare(targetRow.toString(), rowKey.toString()); } } if (1 == comparison) { smallestValue = value; targetRow = rowKey; targetCol = colKey; } } } } } } return smallestValue != null ? new MatrixCell<>(targetRow, targetCol, smallestValue) : null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy