Java - Object Without New Instance - java

I have multiple classes in my program, and I'm trying to find a way to use some methods in one of my other classes. Normally I would just do:
Class obj = new Class();
but that creates a new Instance of it and since I'm using HashMaps, that doesn't work because it creates a new map. I want it to use the same HashMap with stuff already saved in it. What is the best way of doing this?
Edit: Heres an example of the code I'm talking about:
Class #1:
public class Foo{
HashMap<String,Integer> hashmap = new HashMap<String,Integer();
hashmap.put("something", 1);
}
Class #2:
public class Foo2{
Foo f = new Foo();
f.get("something");
}
and nothing shows up for f.get because I created a new version of it...could somebody correct this code for me so I can see what you guys are talking about?

You need to share object references
public class Main {
public static class Foo{
Map<String, Integer> map;
public Foo(Map<String, Integer> map) {
this.map = map; // don't create a new object,
// use one that already exists that can be passed as an argument
}
public void put(String key, Integer value) {
map.put(key, value);
}
public Integer get(String key) {
return map.get(key);
}
}
public static void main(String[] args) {
Map<String, Integer> someMap = new HashMap<>();
someMap.put("aKey", 42);
Foo foo = new Foo(someMap); // the Foo object now references the map you just created
System.out.println(foo.get("aKey")); // prints 42
}
}
Here, you create a Map and pass a copy of its reference as an argument to your class' constructor. Your class saves this reference and uses it to access the same object.
When sharing objects, it's important to know what you are doing so that updates aren't lost/overwritten.

This is also another possible way to do. Extend hashmap and make the class as singleton.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
class ExtHashMap<K,V> extends HashMap<Object,Object> {
private static HashMap<?, ?> map;
public static HashMap<?, ?> getInstance() {
if (map == null) {
map = new HashMap<Object,Object>();
}
return map;
}
private ExtHashMap() {
super();
}
}
public class SampleUtil {
/**
* #param args
*/
public static void main(String args[]) throws Exception {
HashMap map = ExtHashMap.getInstance();
map.put("1", "v1");
HashMap map1 = ExtHashMap.getInstance();
map1.put("2", "v2");
System.out.println(map1.values());
}
}

Related

When a map variable is passed to constructor of different instances, all instances member variables are updated to latest value of map [duplicate]

This question already has answers here:
Is Java really passing objects by value? [duplicate]
(6 answers)
Closed 3 years ago.
Main Class --
package test;
import java.util.Map;
public class Client {
private static ArrayList<Class1> allInstances = new ArrayList<Class1>();
private static Map <String, String> var1 = new HashMap<String, String>();
public static void main(String[] args)
{
var1.put("key1","value1");
Class1 instance1 = new Class1(var1);
allInstances.add(instance1);
var1.put("key2","value2");
Class1 instance2 = new Class1(var1);
allInstances.add(instance2);
getInstances();
}
public static void getInstances() {
for(Class1 c: allInstances) {
System.out.println(c.getClassDetails());
}
}
Class Class1 --
package test
import java.util.Map;
public class Class1 {
private Map <String, String> classDetails;
public Class1(Map <String, String> classDetails) {
this.classDetails = classDetails;
}
public Map <String, String> getClassDetails(){
return this.classDetails;
}
}
Output--
{key2=value2}
{key2=value2}
As we can see from the output above, both instances variable returns the same updated value. Should'nt instance1 return {key1=value1}
Also, if this is the expected behavior, what can be done to tackle this issue.
As it is appeared from your code, you referenced same HashMap to instacne1 and instance2 objects and in getClassDetails method the tostring method of same hashmap will invoked so the outputs is the same , use this code snippet :
import java.util.*;
public class Main {
private static ArrayList<Class1> allInstances = new ArrayList<Class1>();
public static void main(String[] args)
{
Map <String, String> var = new HashMap<String, String>();
var.put("key1","value1");
Class1 instance1 = new Class1(var);
allInstances.add(instance1);
var = new HashMap<String, String>();
var.put("key2","value2");
Class1 instance2 = new Class1(var);
allInstances.add(instance2);
getInstances();
}
public static void getInstances() {
for(Class1 c: allInstances)
System.out.println(c.getClassDetails());
}
}

In class A, I want to go throught the keySet of a HashMap in class B

I want to go through each key in a keySet of a HashMap from another class.
Right now this is what I have:
Admin.java
import java.util.HashMap
public class Admin {
public static HashMap<String, Person> person = new HashMap<String, Person>();
public static void main (String [] args) {
for (String key: person.get("James").getHashMap().keySet()) {
System.out.println(key);
}
}
Person.java
import java.util.HashMap
public class Person {
public static HashMap<String, Book> book = new HashMap<String, Book>();
private static String title = "";
public Book (String titleIn) {
title = titleIn;
}
public HashMap getHashMap(){
return book;
}
}
I think I can't do this beacause I am unable to use HashMap commands on a HashMap that isn't stored in the same class.
Is there another method I could use? Am I calling it wrong from Admin.java?
Thanks!
Your getHashMap method returns a raw HashMap in your Person class.
Raw maps are not parametrized, so the type for their key is Object implicitly.
You need to change it to:
public Map<String, Book> getHashMap(){
return book;
}
... in order to be able to reference a key as String.
Edit
You also need to either change the book variable to instance (as opposed to static), or make the getHashMap method static.
The latter is probably advised against, as it would return the same object for all your Person instances.
Since it is static and public , you are allowed use it from anywhere of your project. Just write
Admin.person
For ex
public class Person {
...
....
public void print() {
for (String key: Admin.person.get("James").getHashMap().keySet()) {
System.out.println(key);
}
}
}

prevent protected variable access from child class without using getter and setter in java

Without using getter and setter method how to prevent modification access from child class if super class has protected Hashmap variable?
This Map is mutable (So i should be able to add the values from super class)So can't use UnmodifiableMap(its only applicable immutable collection object)
Class A
{
protected Map<Integer,Integer> m = new HashMap<Integer,Integer>();
A()
{
m.put(10,11)
m.put(11.12)
}
}
Class B extends A
{
B()
{
super.m.put(34,90) —— I don’t want to give access to child class to add
the value and child class and its only should able to get the values.
}
}
Make the map unmodifiable, and populate it in the construction of A.
class A {
protected final Map<Integer,Integer> m;
A() {
Map<Integer, Integer> tempMap = = new HashMap<>();
tempMap.put(10,11);
tempMap.put(11.12);
this.m = java.util.Collections.unmodifiableMap(tempMap);
}
}
If and when B attempts to modify the map, a ´UnsupportedOperationException´ will be thrown.
If you want A to be able to modify the map, then you'll need a different approach in which the map is private, and a protected getter returns an unmodifiable map.
class A {
private final Map<Integer,Integer> m = new HashMap<>();
A() {
m.put(10,11);
m.put(11.12);
// m remains modifiable within the context of A
}
protected Map<Integer, Integer> getMap() {
return java.util.Collections.unmodifiableMap(m);
}
}
EDIT
If you really don't want to use a getter but still have read-only access, you can use this approach.
class A {
private final Map<Integer,Integer> writableMap = new HashMap<>();
protected final Map<Integer,Integer> m = Collections.unmodifiableMap(writableMap);
A() {
writableMap.put(10,11);
writableMap.put(11.12);
}
}
Using this approach, only m is visible outside A, and is read-only. Within A, you can update writableMap and these changes will be visible in m
Here is a variant of what Steve Chaloner presented in his answer:
public class A {
private final Map<Integer, Integer> map = new HashMap<>();
protected final Map<Integer,Integer> m = Collections.unmodifiableMap(map);
public A() {
map.put(10, 11);
map.put(11, 12);
}
}
The private map is modifiable in the A class and changes will be reflected in the protected m whenever changes are made in map.
It is being used this way in Concurrency In Practice for example.
This should be the best solution Composition:
Implement a new Map and keep an internal private modifiable map like this:
class A {
private Map<Integer,Integer> m = new HashMap<>();
protected Map<Integer, Integer> map = new Map<>() {
//implement interface
public Integer put(Integer key, Integer value) {
throw new UnsupportedOperationException();
}
public Integer get(Object key) {
return m.get(key);
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean containsKey(Object key) {
return m.containsKey(key);
}
public boolean containsValue(Object value) {
return m.containsValue(value);
}
//
// ... And so on
//
// ... with all other methods
}
A() {
m.put(10,11)
m.put(11.12)
}
}
class B extends A {
B() {
super.map.put(34,90) // thorws exception
super.m.put(34,90) // inaccesible
}
}
All modifications are allowed in A via m but subclasses may only acces them by map that was succesfully blocked modifications.

Dictionary of Objects where key is an instance field in Java

I was wondering if it was possible to have a Java dictionary of objects where one of the fields of the object is defined to be the key of the dictionary.
To be more specific, here's what I would like: I have defined a class with three fields. One of these fields is an Integer and is unique to each object. I would like this field to be the key of the dictionary.
Yes, of course it's possible.
Example :
Map<Integer,MyClass> map = new HashMap<Integer,MyClass>();
MyClass myObject = new MyClass(...);
map.put (myObject.getIntegerKey(), myObject);
If you want to hide the details:
public interface HasOwnKey<K> {
public K getKey();
}
public class MyMap<K, V extends HasOwnKey<K>> {
{
private Map<K,V> map = new HashMap<>();
public V put(V value) {
{
return this.map.put(value.getKey(),value);
}
public V get(K key) {
return this.map.get(key)
}
... etc
}
public class MyClass extends HasOwnKey<String> {
...
#Override String getKey() { return this.key; }
}
MyMap<String, MyClass> myMap = new MyMap<>();
MyClass obj = new MyClass();
obj.setKey("abc");
myMap.put(obj);
Unfortunately Java 7 doesn't seem to be smart enough to infer K from a declaration like
public class MyMap<V extends HasOwnKey<K>> {
so you have to provide the Key type in two places and cannot do
MyMap<MyClass> myMap = new MyMap<>();
You can do that easily as follows :
public class CustomClass
{
private int primaryKey;
private int secondaryField;
private int tertiaryField;
public CustomClass(int primaryKey, int secondaryField, int tertiaryField)
{
this.primaryKey = primaryKey;
this.secondaryField = secondaryField;
this.tertiaryField = tertiaryField;
}
public int getPrimaryKey(CustomClass object)
{
return object.primaryKey;
}
}
public class Test
{
public static void main(String[] args)
{
CustomClass object = new CustomClass(10, 20, 30);
Map map = new HashMap<Integer,CustomClass>();
map.put(object.getPrimaryKey(object), object);
}
}
You may also want to consider using Enums for doing the same, if the number of such records is fairly less, as they provide more readability.
If you already have created a List of those objects you can use an aggregate operation in java 8 like this:
Map<Integer, List<MyClass>> theMap = list
.stream()
.collect( Collectors.groupingBy(MyClass::myIntegerKey) );

How to efficiently get the values from a HashMap with a static class?

I have a class with a HashMap<k,v>.
The type of the values of this HashMap is a static class which has two different objects as attributes. i.e.,
public class Example {
private HashMap<String, StaticClassExample> map;
private static class StaticClassExample {
private Object1 o1;
private Object2 o2;
//...
}
//...
}
And my question is how can I do this operation efficiently:
public List<Object1> getAllObject1() {}
I know that I can do: map.values() and then iterate the values collection and get Object1 from each StaticClassExample, but this wouldn't be efficient.
It's possible what I ask or I must create another hashmap for my purpose?
If you don't mind some memory overhead, you could keep a separate list with the o1-values:
public class HashMapList
{
private HashMap<String, StaticClassExample> map = new HashMap<String, HashMapList.StaticClassExample>();
private List<Object> o1List = new LinkedList<Object>();
public static class StaticClassExample
{
private Object o1;
private Object o2;
}
public void addStaticClassExample(String key, StaticClassExample example)
{
StaticClassExample oldVal = map.put(key, example);
if(oldVal != null)
{
o1List.remove(oldVal.o1);
}
o1List.add(example.o1);
}
public StaticClassExample getStaticClassExampleByKey(String key)
{
return map.get(key);
}
public void removeStaticClassExampleByKey(String key)
{
StaticClassExample removed = map.remove(key);
if(removed != null)
{
o1List.remove(removed.o1);
}
}
public List<Object> getAllObject1()
{
return Collections.unmodifiableList(o1List);
}
}
Of course, this requires you to encapsule the HashMap inside the class and never give a straight access to it, because then someone using the class could modify the HashMap directly, and the List would no longer be in sync with the Map. Note that getAllObject1 returns an unmodifiable view of the internal list, so it can't be modified from outside of the class.

Categories

Resources