I am trying to add data to my hashmap if the key does not already exist in the map. For some reason, even if the key does exist, the hashmap adds it anyways. I have no idea why this is happening. My addEntity method is the problem. I am trying to detect of the key is already in the hashmap, and if it is, then do nothing. However, it for some reason will always add the key, no matter if the key already exists.
My data file:
package timeTraveler.mechanics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.entity.EntityLiving;
public class PathingData
{
/**
* Entity data array
*/
public static Map<String[], List<int[]>> allEntityData;
public PathingData()
{
allEntityData = new HashMap<String[], List<int[]>>();
}
/**
* Adds an entity UUID (Unique ID)and MobType to the entity data ArrayList. If the entity already exists inside of the ArrayList, then it skips it.
* #param uuid
*/
public void addEntity(String[] entityData)
{
System.out.println(entityData[0]);
if(!allEntityData.containsKey(entityData))
{
System.out.println("Adding entity!");
allEntityData.put(entityData, new ArrayList<int[]>());
}
else
{
System.out.println("ENTITY ALREADY EXISTS IN ARRAY");
}
}
/**
* Adds data (X, Y, and Z) to the corresponding UUID (Unique ID) for the entity. If the entity's UUID does not exist, then it prints out a line that says the UUID cannot be found.
* #param uuid
* #param data
*/
public void addData(String[] entityData, String data)
{
System.out.println(entityData[0]);
if(allEntityData.containsKey(entityData))
{
System.out.println("Adding data to entity!");
int[] rawData = new int[3];
String[] pureData = data.split(",");
rawData[0] = Integer.parseInt(pureData[0]);
rawData[1] = Integer.parseInt(pureData[1]);
rawData[2] = Integer.parseInt(pureData[2]);
List<int[]> entityLocData = allEntityData.get(entityData);
entityLocData.add(rawData);
allEntityData.put(entityData, entityLocData);
}
else
{
System.out.println("ENTITY DOES NOT EXIST IN ARRAY! :(");
//addEntity(entityData);
}
}
/**
* Gets the data for a specific UUID (Unique ID) for an entity.
* #param uuid
* #return
*/
public List<int[]> getDataForUUID(String[] entityData)
{
List<int[]> entityLoc = allEntityData.get(entityData);
return entityLoc;
}
/**
* Clears all entities and their corresponding data from the map.
*/
public void clearAllEntitiesAndData()
{
allEntityData.clear();
}
/**
* Checks if entity exists inside of array
* #param uuid
* #return
*/
public boolean doesEntityExist(String[] entityData)
{
List<int[]> entityLoc = allEntityData.get(entityData);
if(entityData != null)
{
return true;
}
return false;
}
}
I have made sure that there is only one instance of the variable, and I always refer to that one variable in my .addEntity and .addData. Any ideas?
EDIT: I have just now tried to implement the suggestion proposed. However, it still just prints out the same thing, with timetraveler.core.StringArrayHolder#0 instead of the array. Here is the modified code:
package timeTraveler.mechanics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import timeTraveler.core.StringArrayHolder;
import net.minecraft.entity.EntityLiving;
public class PathingData
{
/**
* Entity data array
*/
public static Map<StringArrayHolder, List<int[]>> allEntityData;
public PathingData()
{
allEntityData = new HashMap<StringArrayHolder, List<int[]>>();
}
/**
* Adds an entity UUID (Unique ID)and MobType to the entity data ArrayList. If the entity already exists inside of the ArrayList, then it skips it.
* #param uuid
*/
public void addEntity(StringArrayHolder entityData)
{
System.out.println(entityData);
if(!allEntityData.containsKey(entityData))
{
System.out.println("Adding entity!");
allEntityData.put(entityData, new ArrayList<int[]>());
}
else
{
System.out.println("ENTITY ALREADY EXISTS IN ARRAY");
}
}
/**
* Adds data (X, Y, and Z) to the corresponding UUID (Unique ID) for the entity. If the entity's UUID does not exist, then it prints out a line that says the UUID cannot be found.
* #param uuid
* #param data
*/
public void addData(StringArrayHolder entityData, String data)
{
System.out.println(entityData);
if(allEntityData.containsKey(entityData))
{
System.out.println("Adding data to entity!");
int[] rawData = new int[3];
String[] pureData = data.split(",");
rawData[0] = Integer.parseInt(pureData[0]);
rawData[1] = Integer.parseInt(pureData[1]);
rawData[2] = Integer.parseInt(pureData[2]);
List<int[]> entityLocData = allEntityData.get(entityData);
entityLocData.add(rawData);
allEntityData.put(entityData, entityLocData);
}
else
{
System.out.println("ENTITY DOES NOT EXIST IN ARRAY! :(");
//addEntity(entityData);
}
}
/**
* Gets the data for a specific UUID (Unique ID) for an entity.
* #param uuid
* #return
*/
public List<int[]> getDataForUUID(StringArrayHolder entityData)
{
List<int[]> entityLoc = allEntityData.get(entityData);
return entityLoc;
}
/**
* Clears all entities and their corresponding data from the map.
*/
public void clearAllEntitiesAndData()
{
allEntityData.clear();
}
/**
* Checks if entity exists inside of array
* #param uuid
* #return
*/
public boolean doesEntityExist(StringArrayHolder entityData)
{
List<int[]> entityLoc = allEntityData.get(entityData);
if(entityData != null)
{
return true;
}
return false;
}
}
and the wrapper:
package timeTraveler.core;
import java.util.ArrayList;
public class StringArrayHolder
{
private String[] data;
public StringArrayHolder()
{
data = new String[2];
}
public void setData(String[] data)
{
this.data = data;
}
public String[] getData()
{
return this.data;
}
#Override
public int hashCode()
{
return 0;
//...
}
#Override
public boolean equals(Object o)
{
if(data.equals(o))
{
return true;
}
return false;
//...
}
}
The problem is that arrays don't override equals nor hashCode methods from Object class, thus even if you add a new String[] with the same values, it will be a different key in your map.
A possible solution would be creating a wrapper class that will hold the String[] for you and override the equals and hashCode methods there.
public class MyStringArrayHolder {
private String[] data;
//class constructor...
//getters and setters for the array...
#Override
public int hashCode() {
//...
}
#Override
public boolean equals(Object o) {
//...
}
}
For the implementations of equals and hashCode methods, you can use Arrays#equals and Arrays#hashCode in this wrapper class.
From your comment:
My addEntity method is the problem. I am trying to detect of the key is already in the hashmap, and if it is, then do nothing. However, it for some reason will always add the key, no matter if the key already exists.
This is what I've explained above. The method Map#containsKey clearly states this:
returns true if and only if this map contains a mapping for a key k such that (key==null ? k==null : key.equals(k))
Since arrays does not override Object#equals, you won't have two similar array keys even if they have the same elements in the same position.
EDIT: based on your current edit, the problems are in the equals and hashCode methods implementation. I've made a basic implementation of the MyStringArrayHolder class and copied/pasted the code of the PathingData class. This works as expected (at least for this case):
class MyStringArrayHolder {
private final String[] data;
//I do not want any client could change the array reference
//this also explains why this field doesn't have a setter
public MyStringArrayHolder(String[] data) {
this.data = data;
}
public String[] getData() {
return this.data;
}
#Override
public int hashCode() {
return Arrays.hashCode(data);
}
#Override
public boolean equals(Object o) {
if (o == null) return false;
if (o == this) return true;
if (o instanceof MyStringArrayHolder) {
MyStringArrayHolder other = (MyStringArrayHolder)o;
return Arrays.equals(this.data, other.data);
}
return false;
}
//just to print in console for testing purposes
#Override
public String toString() {
return Arrays.deepToString(data);
}
}
public class PathingData {
//removed the static modifier, not really sure why you need it like that
public Map<MyStringArrayHolder, List<int[]>> allEntityData;
//current class implementation...
//just to print in console for testing purposes
#Override
public String toString() {
return allEntityData.toString();
}
public static void main(String[] args) {
PathingData pathingData = new PathingData();
String[] example1 = { "hello", "world" };
String[] example2 = { "luiggi", "mendoza" };
String[] example3 = { "hello", "world" };
MyStringArrayHolder holder1 = new MyStringArrayHolder(example1);
MyStringArrayHolder holder2 = new MyStringArrayHolder(example2);
MyStringArrayHolder holder3 = new MyStringArrayHolder(example3);
pathingData.addEntity(holder1);
pathingData.addEntity(holder2);
pathingData.addEntity(holder3);
pathingData.addData(holder1, "1,2,3");
pathingData.addData(holder2, "4,5,6");
pathingData.addData(holder3, "7,8,9");
System.out.println(pathingData);
}
}
Output:
Adding entity!
Adding entity!
ENTITY ALREADY EXISTS IN ARRAY
Adding data to entity!
Adding data to entity!
Adding data to entity!
{[luiggi, mendoza]=[[I#35087359], [hello, world]=[[I#5a7691c0, [I#1e5b02a6]}
Note: the last line containing [I#35087359 is the current hash code of the int[]. I would recommend to change from List<int[]> to List<List<Integer>>, but this implementation is outside the scope of the question :).
Related
The bubble sort sorting in the driver class works fine but I make a new list and try to do insertion sort and it just doesn't sort the list. I was thinking it was something with the setSortBehavior method in the first Listing class but everything I've tried hasn't worked.
package strategydesignpattern;
import java.util.ArrayList;
public class Listing {
protected String title;
protected ArrayList<String> items;
protected SortBehavior theSortBehavior;
/**
* Creates a list with the indicated name
* #param title The title of the list
*/
public Listing(String title)
{
this.title = title;
this.items = new ArrayList<String>();
this.theSortBehavior = new BubbleSort();
}
/**
* Adds an item to the list
* #param item the item you want to add to the list
*/
public void add(String item)
{
items.add(item);
}
/**
* removes an item from the list
* #param item the item you want to remove from the list
*/
public void remove(String item)
{
items.remove(item);
}
/**
* a getter for the name of the list
* #return returns the title of the list
*/
public String getTitle()
{
return title;
}
/**
* sets the sort behavior to whatever is passed in
* #param sortBehavior gets the sort behavior, either insertion or bubble
*/
public void setSortBehavior(SortBehavior sortBehavior)
{
theSortBehavior = sortBehavior;
}
/**
*
* #return returns the sorted list of items
*/
public ArrayList<String> getSortedList()
{
return theSortBehavior.sort(items);
}
/**
*
* #return returns the unsorted list of items
*/
public ArrayList<String> getUnSortedList()
{
return items;
}
}
//////
package strategydesignpattern;
import java.util.ArrayList;
public interface SortBehavior {
public ArrayList<String> sort(ArrayList<String> data);
}
///
package strategydesignpattern;
import java.util.ArrayList;
public class BubbleSort implements SortBehavior{
public ArrayList<String> sort(ArrayList<String> data)
{
String temp;
boolean sorted = false;
while (!sorted) {
sorted = true;
for (int i = 0; i < data.size()-1; i++) {
if (data.get(i).compareTo(data.get(i + 1)) > 0) {
temp = data.get(i);
data.set(i, data.get(i + 1));
data.set(i + 1, temp);
sorted = false;
}
}
}
return data;
}
}
//
package strategydesignpattern;
import java.util.ArrayList;
public class InsertionSort implements SortBehavior{
public ArrayList<String> sort(ArrayList<String> data)
{
for (int j = 1; j < data.size(); j++) {
String current = data.get(j);
int i = j-1;
while ((i > -1) && ((data.get(i).compareTo(current)) == 1)) {
data.set(i+1, data.get(i));
i--;
}
data.set(i+1, current);
}
return data;
}
}
////
package strategydesignpattern;
import java.util.ArrayList;
/**
* Creates lists of information, and displays the sorted versions of the lists
*/
public class ListDriver {
/**
* Creates a new ListDriver
*/
public ListDriver(){}
/**
* Main entryway to the program
* Creates the lists, and displays the sorted lists
*/
public void run() {
Listing shoppingList = new Listing("Grocery List");
shoppingList.add("Apples");
shoppingList.add("Peaches");
shoppingList.add("Cheese");
shoppingList.add("Crackers");
shoppingList.add("Chocolate");
shoppingList.add("Cherries");
shoppingList.add("Bananas");
shoppingList.add("Oranges");
ArrayList<String> sortedGroceryItems = shoppingList.getSortedList();
System.out.println(shoppingList.getTitle());
displayList(sortedGroceryItems);
Listing wishList = new Listing("Wish List");
wishList.setSortBehavior(new InsertionSort());
wishList.add("Bike");
wishList.add("Paddle Board");
wishList.add("Boat");
wishList.add("Truck");
wishList.add("Puzzle");
wishList.add("Monolopy");
wishList.add("Skipping Rope");
wishList.add("Cherry Tree");
ArrayList<String> sortedWishListItems = wishList.getSortedList();
System.out.println("\n" + wishList.getTitle());
displayList(sortedWishListItems);
}
/**
* Loops through and displays each item in the list items
* #param items list to display
*/
private void displayList(ArrayList<String> items){
for(String item : items){
System.out.println("- " + item);
}
}
public static void main(String[] args){
ListDriver driver = new ListDriver();
driver.run();
}
}
It appears that you have assumed the String.compareTo will return 1 to indicate a lexicographical ordering where the string the method is being invoked on follows the argument string. The Documenation states that the return value for String.compareTo is a positive integer to indicate this lexicographical ordering, not specifically 1.
I have try to debug your code. I find that (data.get(i).compareTo(current)) == 1) is not correct. According to the Java String API (https://docs.oracle.com/javase/10/docs/api/java/lang/String.html#compareTo(java.lang.String))
The result is a negative integer if this String object lexicographically precedes the argument string. The result is a positive integer if this String object lexicographically follows the argument string. The result is zero if the strings are equal; compareTo returns 0 exactly when the equals(Object) method would return true.
It says the result is a positive integer.
Following scenario.
Little SpringBoot application with the following classes:
FooDto:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.LinkedList;
import java.util.List;
import org.immutables.value.Value;
#Value.Immutable
#JsonDeserialize(builder = FooDto.Builder.class)
public interface FooDto{
#JsonProperty("fee")
String getFee();
#JsonProperty("fii")
String getFii();
#JsonProperty("url")
String getUrl();
#Value.Default
#JsonProperty("values")
default String[] getValues(){
return new String[0];
}
}
FooJsonMapper:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.springframework.stereotype.Component;
#Component
/*package*/ class FooJsonMapper {
private final ObjectMapper objectMapper;
FooJsonMapper() {
objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
}
public List<FooDto> toDtos(File jsonFile) throws IOException {
return Arrays.asList(objectMapper.readValue(jsonFile, FooDto[].class));
}
}
and a JSON like this:
[
{
"fee":"SOME_MESSAGE",
"fii":"SOME_TECH_MESSAGE",
"url":"/some",
"values":[
"test",
"some"
]
},
{
"fee":"OTHER_MESSAGE",
"fii":"OTHER_TECH_MESSAGE",
"url":"/other",
"values":[
"other",
"some"
]
},
{
"fee":"4711_MESSAGE",
"fii":"4711_TECH_MESSAGE",
"url":"/4711",
"values":[
]
}
]
Somehow when running the code jackson reports the following:
com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `org.some.package.ImmutableFooDto$Builder`, problem: Cannot build FooDto, some of required attributes are not set [fee, fii, url]
at [Source: (File); line: 13, column: 3] (through reference chain: java.lang.Object[][0])
at com.fasterxml.jackson.databind.exc.ValueInstantiationException.from(ValueInstantiationException.java:47) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1907) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.DeserializationContext.handleInstantiationProblem(DeserializationContext.java:1260) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapInstantiationProblem(BeanDeserializerBase.java:1865) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.finishBuild(BuilderBasedDeserializer.java:202) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:217) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:214) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:24) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593) ~[jackson-databind-2.12.3.jar:2.12.3]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3413) ~[jackson-databind-2.12.3.jar:2.12.3]
at org.some.package.FooJsonMapper.toDtos(FooJsonMapper.java:25) ~[classes/:na]
I can confirm that the json is correct as the following line of code creates Objects with the data in them:
return Arrays.asList(objectMapper.readValue(jsonFile, Object[].class));
I also tried using #Value.Style(builder = "new") at the FooDto.class as sugested here: https://immutables.github.io/json.html
Jackson: 2.12.3
org.immutables: 2.8.2
EDIT:
As Requested the ImmutableDTO with Builder:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.annotation.Generated;
/**
* Immutable implementation of {#link FooDto}.
* <p>
* Use the builder to create immutable instances:
* {#code ImmutableFooDto.builder()}.
*/
#SuppressWarnings("all")
#Generated({"Immutables.generator", "FooDto"})
public final class ImmutableFooDto implements FooDto {
private final String fee;
private final String fii;
private final String url;
private final String[] values;
private ImmutableFooDto(ImmutableFooDto.Builder builder) {
this.fee = builder.fee;
this.fii = builder.fii;
this.url = builder.url;
if (builder.values != null) {
initShim.values(builder.values);
}
this.values = initShim.getValues();
this.initShim = null;
}
private ImmutableFooDto(
String fee,
String fii,
String url,
String[] values) {
this.fee = fee;
this.fii = fii;
this.url = url;
this.values = values;
this.initShim = null;
}
private static final int STAGE_INITIALIZING = -1;
private static final int STAGE_UNINITIALIZED = 0;
private static final int STAGE_INITIALIZED = 1;
private transient volatile InitShim initShim = new InitShim();
private final class InitShim {
private String[] values;
private int valuesStage;
String[] getValues() {
if (valuesStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage());
if (valuesStage == STAGE_UNINITIALIZED) {
valuesStage = STAGE_INITIALIZING;
this.values = getValuesInitialize().clone();
valuesStage = STAGE_INITIALIZED;
}
return this.values;
}
void values(String[] values) {
this.values = values;
valuesStage = STAGE_INITIALIZED;
}
private String formatInitCycleMessage() {
ArrayList<String> attributes = new ArrayList<String>();
if (valuesStage == STAGE_INITIALIZING) attributes.add("values");
return "Cannot build FooDto, attribute initializers form cycle" + attributes;
}
}
private String[] getValuesInitialize() {
return FooDto.super.getValues();
}
/**
* #return The value of the {#code fee} attribute
*/
#JsonProperty("fee")
#Override
public String getFee() {
return fee;
}
/**
* #return The value of the {#code fii} attribute
*/
#JsonProperty("fii")
#Override
public String getFii() {
return fii;
}
/**
* #return The value of the {#code url} attribute
*/
#JsonProperty("url")
#Override
public String getUrl() {
return url;
}
/**
* #return A cloned {#code values} array
*/
#JsonProperty("values")
#Override
public String[] getValues() {
InitShim shim = this.initShim;
return shim != null
? shim.getValues().clone()
: this.values.clone();
}
/**
* Copy the current immutable object by setting a value for the {#link FooDto#getFee() fee} attribute.
* An equals check used to prevent copying of the same value by returning {#code this}.
* #param fee A new value for fee
* #return A modified copy of the {#code this} object
*/
public final ImmutableFooDto withFee(String fee) {
if (this.fee.equals(fee)) return this;
String newValue = Objects.requireNonNull(fee, "fee");
return new ImmutableFooDto(newValue, this.fii, this.url, this.values);
}
/**
* Copy the current immutable object by setting a value for the {#link FooDto#getFii() fii} attribute.
* An equals check used to prevent copying of the same value by returning {#code this}.
* #param fii A new value for fii
* #return A modified copy of the {#code this} object
*/
public final ImmutableFooDto withFii(String fii) {
if (this.fii.equals(fii)) return this;
String newValue = Objects.requireNonNull(fii, "fii");
return new ImmutableFooDto(this.fee, newValue, this.url, this.values);
}
/**
* Copy the current immutable object by setting a value for the {#link FooDto#getUrl() url} attribute.
* An equals check used to prevent copying of the same value by returning {#code this}.
* #param url A new value for url
* #return A modified copy of the {#code this} object
*/
public final ImmutableFooDto withUrl(String url) {
if (this.url.equals(url)) return this;
String newValue = Objects.requireNonNull(url, "url");
return new ImmutableFooDto(this.fee, this.fii, newValue, this.values);
}
/**
* Copy the current immutable object with elements that replace the content of {#link FooDto#getValues() values}.
* The array is cloned before being saved as attribute values.
* #param elements The non-null elements for values
* #return A modified copy of {#code this} object
*/
public final ImmutableFooDto withValues(String... elements) {
String[] newValue = elements.clone();
return new ImmutableFooDto(this.fee, this.fii, this.url, newValue);
}
/**
* This instance is equal to all instances of {#code ImmutableFooDto} that have equal attribute values.
* #return {#code true} if {#code this} is equal to {#code another} instance
*/
#Override
public boolean equals(Object another) {
if (this == another) return true;
return another instanceof ImmutableFooDto
&& equalTo((ImmutableFooDto) another);
}
private boolean equalTo(ImmutableFooDto another) {
return fee.equals(another.fee)
&& fii.equals(another.fii)
&& url.equals(another.url)
&& Arrays.equals(values, another.values);
}
/**
* Computes a hash code from attributes: {#code fee}, {#code fii}, {#code url}, {#code values}, {#code roles}.
* #return hashCode value
*/
#Override
public int hashCode() {
int h = 31;
h = h * 17 + fee.hashCode();
h = h * 17 + fii.hashCode();
h = h * 17 + url.hashCode();
h = h * 17 + Arrays.hashCode(values);
return h;
}
/**
* Prints the immutable value {#code FooDto} with attribute values.
* #return A string representation of the value
*/
#Override
public String toString() {
return "FooDto{"
+ "fee=" + fee
+ ", fii=" + fii
+ ", url=" + url
+ ", values=" + Arrays.toString(values)
+ "}";
}
/**
* Utility type used to correctly read immutable object from JSON representation.
* #deprecated Do not use this type directly, it exists only for the <em>Jackson</em>-binding infrastructure
*/
#Deprecated
#JsonDeserialize
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE)
static final class Json implements FooDto {
String fee;
String fii;
String url;
String[] values;
List<String> roles = Collections.emptyList();
boolean rolesIsSet;
#JsonProperty("fee")
public void setFee(String fee) {
this.fee = fee;
}
#JsonProperty("fii")
public void setFii(String fii) {
this.fii = fii;
}
#JsonProperty("url")
public void setUrl(String url) {
this.url = url;
}
#JsonProperty("values")
public void setValues(String[] values) {
this.values = values;
}
#Override
public String getFee() { throw new UnsupportedOperationException(); }
#Override
public String getFii() { throw new UnsupportedOperationException(); }
#Override
public String getUrl() { throw new UnsupportedOperationException(); }
#Override
public String[] getValues() { throw new UnsupportedOperationException(); }
}
/**
* #param json A JSON-bindable data structure
* #return An immutable value type
* #deprecated Do not use this method directly, it exists only for the <em>Jackson</em>-binding infrastructure
*/
#Deprecated
#JsonCreator
static ImmutableFooDto fromJson(Json json) {
ImmutableFooDto.Builder builder = ImmutableFooDto.builder();
if (json.fee != null) {
builder.fee(json.fee);
}
if (json.fii != null) {
builder.fii(json.fii);
}
if (json.url != null) {
builder.url(json.url);
}
if (json.values != null) {
builder.values(json.values);
}
return builder.build();
}
/**
* Creates an immutable copy of a {#link FooDto} value.
* Uses accessors to get values to initialize the new immutable instance.
* If an instance is already immutable, it is returned as is.
* #param instance The instance to copy
* #return A copied immutable FooDto instance
*/
public static ImmutableFooDto copyOf(FooDto instance) {
if (instance instanceof ImmutableFooDto) {
return (ImmutableFooDto) instance;
}
return ImmutableFooDto.builder()
.from(instance)
.build();
}
/**
* Creates a builder for {#link ImmutableFooDto ImmutableFooDto}.
* #return A new ImmutableFooDto builder
*/
public static ImmutableFooDto.Builder builder() {
return new ImmutableFooDto.Builder();
}
/**
* Builds instances of type {#link ImmutableFooDto ImmutableFooDto}.
* Initialize attributes and then invoke the {#link #build()} method to create an
* immutable instance.
* <p><em>{#code Builder} is not thread-safe and generally should not be stored in a field or collection,
* but instead used immediately to create instances.</em>
*/
public static final class Builder {
private static final long INIT_BIT_TITLE = 0x1L;
private static final long INIT_BIT_TECHNICAL_KEY = 0x2L;
private static final long INIT_BIT_URL = 0x4L;
private long initBits = 0x7L;
private long optBits;
private String fee;
private String fii;
private String url;
private String[] values;
private Builder() {
}
/**
* Fill a builder with attribute values from the provided {#code FooDto} instance.
* Regular attribute values will be replaced with those from the given instance.
* Absent optional values will not replace present values.
* Collection elements and entries will be added, not replaced.
* #param instance The instance from which to copy values
* #return {#code this} builder for use in a chained invocation
*/
public final Builder from(FooDto instance) {
Objects.requireNonNull(instance, "instance");
fee(instance.getFee());
fii(instance.getFii());
url(instance.getUrl());
values(instance.getValues());
return this;
}
/**
* Initializes the value for the {#link FooDto#getFee() fee} attribute.
* #param fee The value for fee
* #return {#code this} builder for use in a chained invocation
*/
public final Builder fee(String fee) {
this.fee = Objects.requireNonNull(fee, "fee");
initBits &= ~INIT_BIT_TITLE;
return this;
}
/**
* Initializes the value for the {#link FooDto#getFii() fii} attribute.
* #param fii The value for fii
* #return {#code this} builder for use in a chained invocation
*/
public final Builder fii(String fii) {
this.fii = Objects.requireNonNull(fii, "fii");
initBits &= ~INIT_BIT_TECHNICAL_KEY;
return this;
}
/**
* Initializes the value for the {#link FooDto#getUrl() url} attribute.
* #param url The value for url
* #return {#code this} builder for use in a chained invocation
*/
public final Builder url(String url) {
this.url = Objects.requireNonNull(url, "url");
initBits &= ~INIT_BIT_URL;
return this;
}
/**
* Initializes the value for the {#link FooDto#getValues() values} attribute.
* <p><em>If not set, this attribute will have a default value as defined by {#link FooDto#getValues() values}.</em>
* #param values The elements for values
* #return {#code this} builder for use in a chained invocation
*/
public final Builder values(String... values) {
this.values = values.clone();
return this;
}
/**
* Builds a new {#link ImmutableFooDto ImmutableFooDto}.
* #return An immutable instance of FooDto
* #throws java.lang.IllegalStateException if any required attributes are missing
*/
public ImmutableFooDto build() {
if (initBits != 0) {
throw new IllegalStateException(formatRequiredAttributesMessage());
}
return new ImmutableFooDto(this);
}
private String formatRequiredAttributesMessage() {
List<String> attributes = new ArrayList<String>();
if ((initBits & INIT_BIT_TITLE) != 0) attributes.add("fee");
if ((initBits & INIT_BIT_TECHNICAL_KEY) != 0) attributes.add("fii");
if ((initBits & INIT_BIT_URL) != 0) attributes.add("url");
return "Cannot build FooDto, some of required attributes are not set " + attributes;
}
}
private static <T> List<T> createSafeList(Iterable<? extends T> iterable, boolean checkNulls, boolean skipNulls) {
ArrayList<T> list;
if (iterable instanceof Collection<?>) {
int size = ((Collection<?>) iterable).size();
if (size == 0) return Collections.emptyList();
list = new ArrayList<T>();
} else {
list = new ArrayList<T>();
}
for (T element : iterable) {
if (skipNulls && element == null) continue;
if (checkNulls) Objects.requireNonNull(element, "element");
list.add(element);
}
return list;
}
private static <T> List<T> createUnmodifiableList(boolean clone, List<T> list) {
switch(list.size()) {
case 0: return Collections.emptyList();
case 1: return Collections.singletonList(list.get(0));
default:
if (clone) {
return Collections.unmodifiableList(new ArrayList<T>(list));
} else {
if (list instanceof ArrayList<?>) {
((ArrayList<?>) list).trimToSize();
}
return Collections.unmodifiableList(list);
}
}
}
}
I think the problem is that jackson can't find a way to construct your class.
Here's what works for me
import org.immutables.value.Value;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
#Value.Immutable
#Value.Style(privateNoargConstructor = true) //<<<< this is what you need I think
#JsonSerialize(as = ImmutableVal.class)
#JsonDeserialize(as = ImmutableVal.class)
interface Val {
int a();
#JsonProperty("b")
String second();
}
and
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ValMain {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(
ImmutableVal.builder()
.a(1)
.second("B")
.build());
System.out.println(json);
//{"a":1,"b":"B"}
Val val = objectMapper.readValue(json, Val.class);
System.out.println(val);
//Val{a=1, second=B}
}
}
Then you can even get rid of the DTOs
This question already has answers here:
Java Printing Functions
(2 answers)
Closed 9 years ago.
I need help with these two functions print and printall which really do what the title of the functions says
// Prints a directory of all StockItems with their associated
// price, in sorted order (ordered by SKU).
public void printAll() {
}
// Prints a directory of all StockItems from the given vendor,
// in sorted order (ordered by SKU).
public void print(String vendor) {
}
Here is the full function below. DictionaryADT is a class that is used in implementing Hashtables and BST. The DictionaryADT just consists of functions. It has NOTHING to do with Map.
import data_structures.*;
import java.util.Iterator;
import java.util.Map;
public class ProductLookup {
DictionaryADT<String,StockItem> dictionary;
private int maxSize;
public ProductLookup(int maxSize, DictionaryADT<String,StockItem> dictionary) {
this(maxSize);
this.dictionary = dictionary;
}
// Constructor. There is no argument-less constructor, or default size
public ProductLookup(int maxSize) {
this.maxSize = maxSize;
}
// Adds a new StockItem to the dictionary
public void addItem(String SKU, StockItem item) {
dictionary.insert(SKU,item);
}
// Returns the StockItem associated with the given SKU, if it is
// in the ProductLookup, null if it is not.
public StockItem getItem(String SKU) {
if (SKU == null)
return null;
return dictionary.getValue(SKU);
}
// Returns the retail price associated with the given SKU value.
// -.01 if the item is not in the dictionary
public float getRetail(String SKU) {
if (!dictionary.contains(SKU))
return (float) -.01;
return getItem(SKU).getRetail();
}
public float getCost(String SKU) {
if (!dictionary.contains(SKU))
return (float) -.01;
return getItem(SKU).getCost();
}
// Returns the description of the item, null if not in the dictionary.
public String getDescription(String SKU) {
if (!dictionary.contains(SKU))
return null;
return getItem(SKU).getDescription();
}
// Deletes the StockItem associated with the SKU if it is
// in the ProductLookup. Returns true if it was found and
// deleted, otherwise false.
public boolean deleteItem(String SKU) {
if (SKU == null)
return false;
return dictionary.remove(SKU);
}
// Prints a directory of all StockItems with their associated
// price, in sorted order (ordered by SKU).
public void printAll() {
}
// Prints a directory of all StockItems from the given vendor,
// in sorted order (ordered by SKU).
public void print(String vendor) {
}
// An iterator of the SKU keys.
public Iterator<String> keys() {
return dictionary.keys();
}
// An iterator of the StockItem values.
public Iterator<StockItem> values() {
return dictionary.values();
}
}
Unfortunately it seems like java's Iterator cannot be sorted using built in functions as it is not a collection. You can, however, convert it to a List first, and then sort.
// Prints a directory of all StockItems with their associated
// price, in sorted order (ordered by SKU).
public void printAll() {
// Convert the iterator of SKU's to a List
List SKUList = new ArrayList();
Iterator<String> keyIt = dictionary.keys();
while( keyIt.hasNext() )
SKUList.add(it.next());
// Sort the SKU's
Collections.sort(SKUList);
// Print each item
for(int i=0; i<SKUList.size(); i++){
StockItem item = dictionary.getValue( SKUList.get(i) );
// Print what you want here
}
}
I have two class ,following:
first Class:
package MemoryInterfaces;
import java.util.SortedSet;
import java.util.TreeSet;
/**
*
* #author omid
*/
public class MemoryData<T> {
private Object _datas =null;
public MemoryData() {
}
/**
* #return the _data
*/
public SortedSet<T> getDatas() {
if (this._datas==null) {
this._datas=new TreeSet<T>();
getDataOfDatabase();
}
return (SortedSet<T>)_datas;
}
/**
* #param data the _data to set
*/
public void setDatas(SortedSet<T> datas) {
this._datas=datas;
}
public T getDataOfMemory(int i) {
return (T) getDatas().toArray()[i];
}
public void addItem(T data) {
this.getDatas().add(data);
}
public void remove(T data) {
this.getDatas().remove(data);
}
protected void getDataOfDatabase() {
}
}
second Class:
public class CabinetImpl extends MemoryData<CabinetItem> {
private static SortedSet<CabinetItem> _datas = null;
public CabinetImpl() {
setDatas(_datas);
}
#Override
protected void getDataOfDatabase() {
CabinetDaoImpl _cab = new CabinetDaoImpl();
List<Cabinet> _lst = _cab.getTable();
if (!_lst.isEmpty()) {
for (int i = 0; i < _lst.size(); i++) {
AddToMemory(_lst.get(i).getID(), _lst.get(i).getName(), _lst.get(i).getSub(), _lst.get(i).getDepid());
}
_datas=getDatas();
}
}
private void AddToMemory(int id, String name, int sub, int depid) {
CabinetItem _cab = new CabinetItem(id, name, sub, depid);
addItem(_cab);
}
}
in second Class ,I have a static varible(_datas) be when constructing of cabinetImpl class,_datas transfer to MemoryData but not effect changes in MemoryData on _datas.
Please Help Me!
You are not allowed to override a private variable of a super class in an inherited class. Use the getters and setters of MemoryData
You have two different fields with the same name in different classes.
They are no relationship to each other and different types. If you want to have only one copy I suggest removing one of them.
Im parsing an xml file. My XML handler, my object that holds an Arraylist of arrays, and the main class that runs everything and prints it. The problem is, every time I add an array to my arraylist, it changes the all of the previously added arrays to the same as the current. I thought it was just a static problem but once I took static out of everything it still is doing the same thing. Help please I need to have this done asap.
Here is my handler:
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyXMLHandler extends DefaultHandler {
public int counter = 0;
public String[] part = new String[4];
Boolean currentElement = false;
String currentValue = null;
public SitesList sitesList = null; /this used to be static
public SitesList getSitesList() { //this used to be static
return sitesList;
}
public void setSitesList(SitesList sitesList) { //this used to be static
MyXMLHandler handle = new MyXMLHandler(); //thats why the object
handle.sitesList = sitesList;
}
/**
* Called when tag starts ( ex:- <name>text</name> -- <name> )
*/
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentElement = true;
if (localName.equals("string-array")) {
/** Start */
String attr = attributes.getValue("name");
sitesList = new SitesList(attr);
}
}
/**
* Called when tag closing ( ex:- <name>text</name> -- </name> )
*/
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
currentElement = false;
/** set value */
if (counter == 4) {
sitesList.addPart(part);
counter = 0;
}
if (localName.equalsIgnoreCase("item")) {
part[counter] = currentValue;
counter++;
}
currentValue = "";
}
/**
* Called to get tag characters ( ex:- <name>text</name> -- to get
* text Character )
*/
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (currentElement) {
currentValue = new String(ch, start, length);
currentElement = false;
}
}
}
Here is my SitesList object
import java.util.ArrayList;
/** Contains getter and setter method for varialbles */
public class SitesList {
/** Variables */
private ArrayList<String[]> part = new ArrayList<String[]>();
/**
* In Setter method default it will return arraylist change that to add
*/
public SitesList(String c) {
String[] comp = new String[1];
comp[0] = c;
part.add(comp);
// company name is part(0)[0]
}
public String getCompany() {
return this.part.get(0)[0];
}
public ArrayList<String[]> getPart() {
return part;
}
public void addPart(String[] name) {
part.add(name);
}
public String getName(int i) {
return this.part.get(i)[0];
}
public String getComp1(int i) {
return this.part.get(i)[1];
}
public String getComp2(int i) {
return this.part.get(i)[2];
}
public String getComp3(int i) {
return this.part.get(i)[3];
}
public int getSize() {
return this.part.size();
}
}
You're reusing part, i.e. you add it multiple times but overwrite its contents. ArrayList is innocent here :)
Change the adding part to this:
if (counter == 4) {
sitesList.addPart(part);
//create a new array
part = new String[4];
counter = 0;
}
Or, as of Java 6:
if (counter == 4) {
//add a copy to the list
sitesList.addPart(Arrays.copyof(part, part.length));
counter = 0;
}
In reality, the List's values are not changing when the next value is added, but the array part is changed. What I mean is, the List has, at each location, a reference to the same array, which you call part. In other words, the List does not actually copy of the object but stores something (think of it as a "variable") that refers to the object.
So naturally, if you change the object the List is referring to at any index, you will see those changes when you pull out of the List. To solve this problem, create a new array every time you add to the list explicitly using the new keyword (or you can clone the array every time you add).