Combining Hashtables without unifying interface - java

For a lot of implementation reasons (Using Java ME 1.4 with very limited libraries), I have no access to HashMap or any kind of Map interface. In combination with this, I have to use Hashtable, which in the libraries I'm using does not inherit anything.
Yes, there is absolutely no way for me to get around the implementation and libraries that I'm using.
So I have two Hashtables. I need to make one new Hashtable instance that accesses and changes the two "backing" instances. Since Hashtable does not inherit anything, is there any way I could do this? I've tried a rudimentary composing strategy that just goes through an array of tables, but there are some serious problems with that. Specifically, put(key, object) is difficult because there's no way to tell which map it is being backed to.
Any suggestions on a strategy to do this or am I stuck?
public class Scope {
private final Hashtable publicVars;
private final Hashtable publicMethods;
private final Hashtable publicReturning;
private final Hashtable privateVars;
private final Hashtable privateMethods;
public Scope() {
publicMethods = new Hashtable();
publicReturning = new Hashtable(0);
publicVars = new Hashtable();
privateVars = new Hashtable();
privateMethods = new Hashtable();
}
public Scope(Scope scope) {
publicVars = scope.publicVars;
publicMethods = scope.publicMethods;
publicReturning = scope.publicReturning;
privateVars = new Hashtable();
privateMethods = new Hashtable();
// Here's my problem - I need changes made to publicVars to also affect scope.privateVars (and the same to methods)
publicVars.putAll(scope.privateVars);
publicMethods.putAll(scope.privateMethods);
}

private static final class MapGroup {
private final List maps = new ArrayList();
public MapGroup(Hashtable start) {
maps.add(start);
}
public MapGroup(MapGroup group) {
for (int x = 0; x < group.maps.size(); x++) {
maps.add(group.maps.get(x));
}
}
public void add(Hashtable h) {
maps.add(h);
}
public Enumeration keys() {
return new Enumeration() {
private final Enumeration[] enumerations;
private int i;
{
enumerations = new Enumeration[maps.size()];
for (int x = 0; x < maps.size(); x++) {
enumerations[x] = ((Hashtable) maps.get(x)).keys();
}
}
public boolean hasMoreElements() {
return enumerations[i].hasMoreElements()
|| (++i < enumerations.length && enumerations[i].hasMoreElements());
}
public Object nextElement() {
// needed to increment i
return hasMoreElements() ? enumerations[i].nextElement() : null;
}
};
}
public Enumeration elements() {
return new Enumeration() {
private final Enumeration[] enumerations;
private int i;
{
enumerations = new Enumeration[maps.size()];
for (int x = 0; x < maps.size(); x++) {
enumerations[x] = ((Hashtable) maps.get(x)).elements();
}
}
public boolean hasMoreElements() {
return enumerations[i].hasMoreElements()
|| (++i < enumerations.length && enumerations[i].hasMoreElements());
}
public Object nextElement() {
// needed to increment i
return hasMoreElements() ? enumerations[i].nextElement() : null;
}
};
}
public boolean contains(Object value) {
for (int x = 0; x < maps.size(); x++) {
if (((Hashtable) maps.get(x)).contains(value)) {
return true;
}
}
return false;
}
public boolean containsKey(Object key) {
for (int x = 0; x < maps.size(); x++) {
if (((Hashtable) maps.get(x)).containsKey(key)) {
return true;
}
}
return false;
}
public Object get(Object key) {
for (int x = 0; x < maps.size(); x++) {
if (((Hashtable) maps.get(x)).containsKey(key)) {
return ((Hashtable) maps.get(x)).get(key);
}
}
return null;
}
public Object put(Object key, Object value) {
for (int x = 0; x < maps.size(); x++) {
if (((Hashtable) maps.get(x)).containsKey(key)) {
return ((Hashtable) maps.get(x)).put(key, value);
}
}
return ((Hashtable) maps.get(maps.size() - 1)).put(key, value);
}
public Object remove(Object key) {
// Nothing is ever removed - don't worry
return null;
}
public void clear() {
}
public int size() {
int s = 0;
for (int x = 0; x < maps.size(); x++) {
s += ((Hashtable) maps.get(x)).size();
}
return s;
}
public boolean isEmpty() {
return size() == 0;
}
}
Thanks for making me have to think about this guys. I wrote this and it works for me.

Related

How to improve performance of iteration through a HashMap in Java?

Does anybody have any idea about how I could improve the performance of this method? Note that this.allActions is a hashmap with around half a million keys.
Maybe there is a faster way of iterating through a HashMap that I don't know.
public String get_random_legal_action(String stateJSON) {
Collections.shuffle(this.allActionsKeys);
boolean legal;
HashMap<String, Integer> state = new Gson().fromJson(stateJSON, this.stateType);
for (String action : this.allActionsKeys) {
legal = true;
for (Map.Entry<String, Integer> precondition : this.allActions.get(action).precondition.entrySet()) {
try {
if (!state.get(precondition.getKey()).equals(precondition.getValue())) {
legal = false;
break;
}
} catch (NullPointerException e) {
if (!this.immutableProps.contains(precondition.getKey())) {
legal = false;
break;
}
}
}
if (legal)
return action;
}
return null;
}
Convert the HashMap to LinkedHashMap to improve the performance,
the complexity of Get O(1), Contains O(1) and Next O(1)
, You can create custom Key class and update hashCode() function
Use it in like LinkedHashMap<Key, Integer>
static class Key {
private static final int R = 256;
private static final long Q = longRandomPrime();
private String k;
public Key(String k) {
this.k = k;
}
public String key() {
return k;
}
#Override
public int hashCode() {
return Long.hashCode(hash());
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null)
return false;
if (getClass() != o.getClass())
return false;
Key other = (Key) o;
return k.equals(other.k);
}
#Override
public String toString() {
return k;
}
private long hash() {
long h = 0;
for (int j = 0; j < k.length(); j++) {
h = (R * h + k.charAt(j)) % Q;
}
return h;
}
private static long longRandomPrime() {
BigInteger prime = BigInteger.probablePrime(31, new Random());
return prime.longValue();
}
}

How can i access a private array with no getter Method from another class? [duplicate]

This question already has answers here:
How to read the value of a private field from a different class in Java?
(14 answers)
Closed 4 years ago.
So guys im trying to access a private Array from another class. Is there a way to access said array without a get-Method for the array?
public class Entity {
private int key;
private int value;
public Entity(int k, int v) {
key = k;
value = v;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public void setValue(int v) {
value = v;
}
public void setKey(int k) // selbst geadded
{
key = k;
}
}
Those are the elements that are contained in the array.
public class Relation {
private Entity[] map;
public Relation(int n) {
map = new Entity[n]; // größe des neuen feldes
}
public int size() {
return map.length;
}
public Entity extract(int i) {
if (i >= map.length || i < 0 || map[i] != null) {
return null;
}
int key = map[i].getKey();
int value = map[i].getValue();
map[i] = null;
return new Entity(key, value);
}
public boolean into(Entity e) {
for (int i = 0; i < size(); i++) {
if (map[i] == null) {
map[i] = e;
return true;
}
}
return false;
}
public static void main(String[] args) {
}
}
Relation is the Method im supposed to use. This class contains the private array which im trying to access.
public class Use {
public static boolean substitute(Relation rel, Entity e) {
if (rel.size() > 0) {
rel.map[0] = e; // "map has private acccess in Relation"
return true;
}
return false;
}
public static Relation eliminate(Relation rel, int k) {
int counter = 0;
for (int i = 0; i < rel.size(); i++) {
if (map[i] != k) // // "cannot find symbol map"
{
counter++;
}
}
}
}
And this is the class in which im trying to access the array. The methods here are not finished yet since im getting errors whenever im trying to access the map in the Relation class in any why since I cant figure it out.
To access fields, you need a FieldInfo:
Type relationType = typeof(Relation);
FieldInfo fieldRelationMap = relationType.GetField("map",
BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo has a GetValue and a SetValue

How to pass my object into another objects field?

I am trying to fill UCFCourse courseOne in my constructor with a courses[] object in fillWithCourses().UCFCourse courseOne does populate outside of the constructor but will not go into it.
public class UCFSemester<courses> {
private static UCFCourse courseOne;
private static double totalSemesters;
private static double completionTime;
static boolean fillSemester = true;
public UCFSemester(UCFCourse courseOne, UCFCourse[] coursetwo) {
this.courseOne = courseOne;
}
public static UCFCourse getcourseOne() {
return courseOne;
}
public static void setCoursesone(UCFCourse courses) {
courseOne = courses;
}
public static void fillWithCourses(UCFCourse courses[], int l) {
int x = 0;
while (fillSemester) {
for (int n = 0; n < 5; n++) {
if (x != n && courses[x].getCourseLevel() < courses[n].getCourseLevel()) {
setCoursesone(courses[x]);
}
}
fillSemester = false;
}
}
}
Side question.How can I access this all in a non-static way?I need the entire thing to be non-static but no matter what I do I can't get it.Thanks!
You can simply do it by creating a List like this:
public class UCFSemester {
private List<UCFCourse> courseList = new ArrayList<>();
public UCFCourse getCourse(int index) {
return courseList.get(index);
}
public void addCourses(UCFCourse[] courses) {
for(int x = 0; x < courses.length; x++) {
courseList.add(courses[x]);
}
}
}
Here, I'm assuming that you are passing the UCFCourse[] array with all the course details that are there in that particular semester.
addCourses() function will take this array and then add all the corresponding courses to the List.
getCourse() function will return you any particular course from the List (Using Index). You can also modify the search in any way you want.

Implement my own Array Method Help Java

How would I implement my own method on an element of my own array?
for example, im trying to make a inventory system that if (INVENTORY[X].isValidID() == TRUE)
Then it returns true,
how would i do that?
public void addInv(int ITEM_ID) {
for(int x = 0; x < MAX_STORAGE; x++) {
if(INVENTORY[x].isValidID() == true ) {
}
}
}
public static boolean isValidID(int X) {
return true;
}
You are likely looking for something like this.
public void addInv(int ITEM_ID) {
for(int x = 0; x < MAX_STORAGE; x++) {
if(isValidID(INVENTORY[x])) {
}
}
}
public static boolean isValidID(int X) {
return true;
}

GreenDao - caching of custom data does not work correctly

I have an entity with 3 one-to-many relations
private List<Data1> Data1;
private List<Data2> Data2;
private List<Data3> Data3;
and I want to summurize this data in a manually created list (TotalData just combines the three lists, for easier management...)
private transient TotalData mTotalData;
public TotalData getTotalData()
{
if (mTotalData == null)
mTotalData = new TotalData(getData1(), getData2(), getData3());
return mTotalData;
}
I load my entity with DaoSession.get...Dao().load(id)... On first creation everything works fine, on second creation, my mTotalData already exists and contains empty sublists... Why?
EDIT: my TotalData implementation
All data in the TotalData class are Entities!
public class WWorkoutObjectList
{
private ComparatorWWorkoutObject mComparator = new ComparatorWWorkoutObject();
private List<WWorkoutObject> mObjects = new ArrayList<WWorkoutObject>();
public WWorkoutObjectList(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
{
init(wExercises, wCardio, wPause);
}
public void init(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
{
synchronized (mObjects)
{
mObjects.clear();
for (int i = 0; i < wExercises.size(); i++)
mObjects.add(new WWorkoutObject(wExercises.get(i)));
for (int i = 0; i < wCardio.size(); i++)
mObjects.add(new WWorkoutObject(wCardio.get(i)));
for (int i = 0; i < wPause.size(); i++)
mObjects.add(new WWorkoutObject(wPause.get(i)));
sort();
}
}
public void add(WWorkoutObject wObject)
{
synchronized (mObjects)
{
mObjects.add(wObject);
sort();
}
}
public int size()
{
return mObjects.size();
}
public WWorkoutObject get(int index)
{
return mObjects.get(index);
}
public WWorkoutObject remove(int index)
{
return mObjects.remove(index);
}
// ----------------
// Hilfsfunktionen
// ----------------
public WExercise getNextExercise(int currentIndex)
{
synchronized (mObjects)
{
for (int i = currentIndex + 1; i < mObjects.size(); i++)
{
if (mObjects.get(i).isWCardio())
return null;
if (mObjects.get(i).isWExercise())
return mObjects.get(i).getWExercise();
}
}
return null;
}
public int getFragmentCount()
{
int counter = 0;
synchronized (mObjects)
{
for (int i = 0; i < mObjects.size(); i++)
{
if (mObjects.get(i).isFragmentObject())
counter++;
}
}
return counter;
}
public WWorkoutObject getFragmentObject(int fragmentIndex)
{
if (fragmentIndex < 0 || fragmentIndex >= mObjects.size())
return null;
int counter = 0;
synchronized (mObjects)
{
for (int i = 0; i < mObjects.size(); i++)
{
if (mObjects.get(i).isFragmentObject())
{
if (counter == fragmentIndex)
return mObjects.get(i);
counter++;
}
}
}
return null;
}
public List<WWorkoutObject> getFragmentsObjectsList()
{
List<WWorkoutObject> list = new ArrayList<WWorkoutObject>();
synchronized (mObjects)
{
for (int i = 0; i < mObjects.size(); i++)
{
if (mObjects.get(i).isFragmentObject())
list.add(mObjects.get(i));
}
}
return list;
}
public List<WWorkoutObject> list()
{
return mObjects;
}
// ----------------
// private Funktionen
// ----------------
private void sort()
{
Collections.sort(mObjects, mComparator);
}
}
Edit2: Flow example
I create an activity and load my Entity with id 1 (DaoSession.load(1))
I call getTotalData() => mTotalData is correct
I turn the screen and reload my now CACHED Entity with id 1 (DaoSession.load(1))) => mTotalData != null but all fields of it are empty... Because it is not null, if I now call getTotalData(), I get a TotalData object that did not update it's values... It looks like an object that was created with an empty constructor (which does not even exist)
I may solve that if I add a isInitialised variable to my TotalData and check this variable in getTotalData()... But still I don't know how the caching is working and why it's not working with my custom field...
Edit3
I am thankful for the feedback, but I think it's still not clear what exactly the problem is.
// Activity onCreate
public void onCreate(Bundle savedInstanceState)
{
WWorkout workout = DaoSession.load(1);
WWorkoutObjectList sortedData = workout.getWWorkoutObjects();
}
// Dao Entity custom function
public WWorkoutObjectList getWWorkoutObjects()
{
// I make sure, with calling the getter functions, that I load all sub entities before creating the list!!!
if (wWorkoutObjectList == null)
wWorkoutObjectList = new WWorkoutObjectList(getWExercise(), getWCardio(), getWPause());
return wWorkoutObjectList;
}
What I do:
I call getWWorkoutObjects() and get all correct data (all lists in WWorkout are loaded and sortedData is correct and filled
I NEVER edit data!!!
I recreate the activity (i.e. turn the screen) and get a correct entity (all lists in WWorkout are correct), BUT mObjects in sortedData is empty, but it exists already!!! Why?
As far as I understand, mObjects should be null or it should hold all data from the entity, but it can't differ, because the only constructor that exists is the one you can see above (that implicitly loads the sub lists of the entity).
Btw, the init function was private before, I only have made it public for a workaround and I did NOT edit any data to get this behaviour.
Probably the problem doesn't lie within the scope of greendao.
Remember that for example on orientation change the actual activity gets destroyed and recreated. Thus a private field of your activity is not garanteed to stay the same on orientation change. You have to take care of the correct state of your fields yourself.
You can do that:
by initializing your fields in onCreate()
by saving the state of your fields in onPause() and restoring it in onResume()
Of course you can also prevent your activity from being recreated on orientation changes. There are a lot posts about how to do that.
Try to move DaoSession.load(1) in the onCreate-method and call getTotalData() there as well. If you already have done that, please post your onCreate-method.
On top of that I'd recommend the following minor changes to your class.
Especially using synchronized on the methods, because there may be strange behaviours if variables you use inside the synchronized block, but that are defined outside the block.
public class WWorkoutObjectList
{
private ComparatorWWorkoutObject mComparator = new ComparatorWWorkoutObject();
private List<WWorkoutObject> mObjects = new ArrayList<WWorkoutObject>();
public WWorkoutObjectList(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
{
init(wExercises, wCardio, wPause);
}
public synchronized void init(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
{
mObjects.clear();
if (wExercises != null) {
for (WExercise we : wExercises) {
mObjects.add(new WWorkoutObject(we));
}
}
if (wCardio != null) {
for (WCardio wc : wCardio) {
mObjects.add(new WWorkoutObject(wc));
}
}
if (wPause != null) {
for (WPause wp : wPause) {
mObjects.add(new WWorkoutObject(wp));
}
}
sort();
}
public synchronized void add(WWorkoutObject wObject)
{
mObjects.add(wObject);
sort();
}
public int size()
{
return mObjects.size();
}
public WWorkoutObject get(int index)
{
return mObjects.get(index);
}
public synchronized WWorkoutObject remove(int index)
{
return mObjects.remove(index);
}
// ----------------
// Hilfsfunktionen
// ----------------
public synchronized WExercise getNextExercise(int currentIndex)
{
for (int i = currentIndex + 1; i < mObjects.size(); i++)
{
if (mObjects.get(i).isWCardio())
return null;
if (mObjects.get(i).isWExercise())
return mObjects.get(i).getWExercise();
}
return null;
}
public synchronized int getFragmentCount()
{
int counter = 0;
for (WWorkoutObject wo : mObjects)
{
if (wo.isFragmentObject())
counter++;
}
return counter;
}
public synchronized WWorkoutObject getFragmentObject(int fragmentIndex)
{
if (fragmentIndex < 0 || fragmentIndex >= mObjects.size())
return null;
int counter = 0;
for (WWorkoutObject wo : mObjects)
{
if (wo.isFragmentObject())
{
if (counter == fragmentIndex)
return mObjects.get(i);
counter++;
}
}
return null;
}
public synchronized List<WWorkoutObject> getFragmentsObjectsList()
{
List<WWorkoutObject> list = new ArrayList<WWorkoutObject>();
for (WWorkoutObject wo : mObjects)
{
if (wo.isFragmentObject())
list.add(wo);
}
return list;
}
public synchronized List<WWorkoutObject> list()
{
ArrayList<WWorkoutObject> result = new ArrayList<WWorkoutObject>();
for (WWorkoutObject wo : mObjects)
result.add(wo);
return result;
}
// ----------------
// private Funktionen
// ----------------
private void sort()
{
Collections.sort(mObjects, mComparator);
}
}

Categories