i have the code like this when i create it like this
public final class PhpArray extends AbstractMap
{
private TreeMap t;
private HashMap m;
public PhpArray() {
this.t = new TreeMap(Request.PHP_ARRAY_KEY_COMPARATOR);
this.m = null;
}
#Override
public Object put(final Object key, final Object value) {
if (this.m != null) {
return this.m.put(key, value);
}
try {
return this.t.put(key, value);
}
catch (ClassCastException e) {
this.m = new HashMap(this.t);
this.t = null;
return this.m.put(key, value);
}
}
#Override
public Set entrySet() {
if (this.t != null) {
return this.t.entrySet();
}
return this.m.entrySet();
}
public int arraySize() {
if (this.t == null) {
throw new IllegalArgumentException("The passed PHP \"array\" is not a sequence but a dictionary");
}
if (this.t.size() == 0) {
return 0;
}
return 1 + this.t.lastKey();
}
}
but when i update my project i got error in the code
return 1 + this.t.lastKey();
the error is an arguments + is undefined.. why like that ? and how to fix the problem ?
TreeMap is a generic class but in the code in your question you have used it without type parameters. This means that this line of your code:
private TreeMap t;
is essentially this:
private TreeMap<Object, Object> t;
In other words t.lastKey() returns an Object and the operator + can't be used with Object because an Object is not a number.
Perhaps you meant to call method size() rather than method lastKey()?
Perhaps this tutorial will help?
Related
i've a rather complex problem. I'am currently developing a a little groovy based script language for an ERP System. The functions and syntax of "my" script language are based on the already existing old FO language which is used by the erp system.
Therefore: I'am getting values from the ERP with calls like h.fieldname, where h the currently selected dataset is and fieldname the name of the field I want my field value from.
I get the field value e.g. of type String. What I now want is to extend these strings I retrieve with a few functions, which are based on the "old" syntax.
// some samples
// get last 3 characters
h.fieldname >> 3
// get first 4 characters
h.fieldname << 4
// should still work even if h.fieldname, returns something which extends String but is not a String
assert h.fieldname == "Foo"
UPDATE
I tried to make use of the answer of #daggett, here my approach:
public abstract class BaseScript extends Script implements GroovyObject {
#Override
public Object run() {
Object o = null;
try {
final ExpandoMetaClass metaClass = new ExpandoMetaClass(String.class, false, true);
//Closure c = { int x-> delegate[-x..-1] };
//ClosureMetaMethod foo = new ClosureMetaMethod​("rightShift ", c , doCall);
metaClass.initialize();
o = runCode();
} catch (Exception e) {
this.onerror(e);
} finally {
this.always();
}
return o;
}
public abstract Object runCode();
public Object always() {
return null;
}
public Object onerror(Object ex) {
if (ex instanceof Exception) {
Exception e = (Exception) ex;
e.printStackTrace();
}
return null;
}
}
But honestly i've no idea how to implement it and I also can't find any example.
UPDATE 2 and solution
Based on the answer of #daggett.
package groovy.runtime.metaclass.java.lang;
import groovy.lang.DelegatingMetaClass;
import groovy.lang.MetaClass;
public class StringMetaClass extends DelegatingMetaClass {
public StringMetaClass(Class<?> theClass) {
super(theClass);
}
public StringMetaClass(MetaClass metaClass) {
super(metaClass);
}
#Override
public Object invokeMethod(Object object, String name, Object[] args) {
// implementiert "test" >> 3
if (name.equals("rightShift")) {
if (args.length == 1) {
if (args[0] instanceof Integer) {
String str = object.toString();
int x = ((Integer) args[0]).intValue();
if (str.length() > x) {
return str.substring(str.length() - x);
}
return str;
} else {
throw new IllegalArgumentException("wrong argument type, should be integer");
}
} else {
throw new IllegalArgumentException("too many arguments");
}
}
// implementiert "test" << 3
if (name.equals("leftShift")) {
if (args.length == 1) {
if (args[0] instanceof Integer) {
String str = object.toString();
int x = ((Integer) args[0]).intValue();
if (str.length() > x) {
return str.substring(0,x);
}
return str;
} else {
throw new IllegalArgumentException("wrong argument type, should be integer");
}
} else {
throw new IllegalArgumentException("too many arguments");
}
}
else {
return super.invokeMethod(object, name, args);
}
}
}
you can't extend string class because it's final, however in groovy you can add new methods to string class with help of metaclass
String.metaClass.rightShift = { int x-> delegate[-x..-1] }
"1234567890" >> 3
returns
890
in the same way implement the method leftShift for <<
the last request (assert s1==s2) is not relevant because String is a final class (not extendable)
Sometimes methods have the only difference somwhere in the middles of their bodies and it's difficult to generalize them or extract common part of code to a single method.
Question itself: How would you refactor the following implementations of interface methods to avoid duplicate code around for loop body?
interface MyInterface {
Integer myInterfaceMethod(String inputStr);
Integer myInterfaceOtherMethod(String inputStr)
}
class MyClass implements MyInterface {
public Integer myInterfaceMethod(String inputStr) {
#Override
try {
List<String> listDependingOnString = getListByString(inputStr);
Integer result = -1;
if (inputStr != null) {
result = 0;
for (String str : listDependingOnString) {
// Some different code, given just for example
result += str.length();
}
}
return result;
} catch (Exception e) {
exceptionProcessing(e);
return null;
}
}
#Override
public Integer myInterfaceOtherMethod(String inputStr) {
try {
List<String> listDependingOnString = getListByString(inputStr);
Integer result = -1;
if (inputStr != null) {
result = 0;
for (String str : listDependingOnString) {
// Some different code, given just for example
System.out.println(str);
++result;
}
}
return result;
} catch (Exception e) {
exceptionProcessing(e);
return null;
}
}
}
For this particular example, a lambda would work nicely:
private Integer computeStringFunction(String inputStr, BiFunction<Integer,String,Integer> accumulator) {
try {
List<String> listDependingOnString = getListByString(inputStr);
Integer result = -1;
if (inputStr != null) {
result = 0;
for (String str : listDependingOnString) {
result = accumulator.apply(result, str);
}
}
return result;
} catch (Exception e) {
exceptionProcessing(e);
return null;
}
public Integer myInterfaceMethod(String inputStr) {
return computeStringFunction(inputStr,
(Integer oldValue, String str) -> oldValue + str.length());
}
public Integer myInterfaceOtherMethod(String inputStr) {
return computeStringFunction(inputStr,
(Integer oldValue, String str) -> {
System.out.println(str);
return oldValue + 1;
});
}
"accumulator" here is a function that takes an integer and a string and returns another integer, and whose intent is to keep a "running total" of some sort.
BiFunction documentation
Note: not tested
The key to remove duplicate pattern in codes is to abstract the common part to one place and then find a way to pass the different part of "code pieces" as parameters to execute, for languages in which function is first class citizen(JavaScript, Python), you can always wrap the "code pieces" as functions. But it's not applicable for Java because method in Java is not a value, one way to resolve it is to define interfaces, and then pass the instance of a class which implements the interface as parameters, with lambda expression in Java 8 it can be more simpler.
Take the code in question as example, the common pattern is:
iterate the list and process each item
accumulate the result of each item and return
Then we can define two interfaces:
#FunctionalInterface
public interface ItemHandler<T, R> {
/**
* Takes input item of type T, then returns result of type R
*/
R handle(T t);
}
And another interface to accumulate the result:
#FunctionalInterface
public interface ItemResultAccumulator<T> {
T accumulate(T t1, T t2);
}
and then your code could be refactored as(I removed all exception handling and null checking code, to make the code less verbose to view):
public class MyClass implements MyInterface {
private static final ItemResultAccumulator<Integer> ADDER = (t1, t2) -> t1 + t2;
#Override
public Integer myInterfaceMethod(String inputStr) {
return processList(getListByString(inputStr), s -> s.length(), ADDER);
}
#Override
public Integer myInterfaceOtherMethod(String inputStr) {
return processList(getListByString(inputStr), s -> {
System.out.println(s);
return Integer.valueOf(1);
}, ADDER);
}
private Integer processList(List<String> list, ItemHandler<String, Integer> handler, ItemResultAccumulator<Integer> accumulator) {
Integer result = 0;
if (list != null && list.size() > 0) {
for (String item : list) {
result = accumulator.accumulate(result, handler.handle(item));
}
}
return result;
}
private List<String> getListByString(String inputStr) {
// Your logic to generate list by input
return Lists.newArrayList(inputStr.split(","));
}
}
This is a little of my thinking of this problem, hope this could be helpful:-)
I am getting duplicate keys in my cacheIterator.
I'm calling a web service using SOAP to rate policies for an insurance company. I am attempting to use a Cachebuilder / loader to store the DTO's as a key and the response from the service as a value. From what I've researched, the .get and .getUnchecked methods will get a value from the cache and if it's not there, it will load that value into the cache.
here is some code:
public class CacheLoaderImpl
{
private static CacheLoaderImpl instance = null;
private static LoadingCache<PolicyDTO, RatingServiceObjectsResponse> responses;
protected CacheLoaderImpl()
{
responses = CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(
new CacheLoader<PolicyDTO, RatingServiceObjectsResponse>() {
public RatingServiceObjectsResponse load(PolicyDTO key)
throws Exception
{
return getResponse(key);
}
});
}
public static CacheLoaderImpl getIntance()
{
if(instance == null)
{
instance = new CacheLoaderImpl();
}
return instance;
}
public LoadingCache<PolicyDTO, RatingServiceObjectsResponse> getResponses()
{
return responses;
}
public RatingServiceObjectsResponse getResponse(PolicyDTO key) throws ExecutionException
{
RatingServiceObjectsResponse response = new RatingServiceObjectsResponse();
try
{
response = new CGIRatabaseServiceImpl().getCoverages(key);
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
return response;
}
}
And this is where I call the get method:
RatingServiceObjectsResponse response = CacheLoaderImpl.getIntance().getResponses().get(policy.toCoveragesCallDTO());
I was under the assumption that maybe it was comparing memory addresses which would be different so I overwrote the toString method to convert the DTO object to JSON. Upon inspecting the cache I can see that the keys are exactly the same with a compare tool. Yet, they're still being stored and calling the service every single time. I tried overwriting the equals method on PolicyDTO but it is never hit when I debug.
How can I make the cacheloader only load values of different keys and pull existing values out as it is originally intended?
I think I just don't have a solid idea how the cacheLoader actually works. I appreciate any help or suggestions.
PolicyDTO class:
public class PolicyDTO extends AbstractDto implements IPolicyDTO
{
private ArrayList<ILineOfBusinessDTO> lobDTOs = new ArrayList<ILineOfBusinessDTO>();
private String pcInd;
private String ratingEffectiveDate;
private String companyName;
public String getPcInd()
{
return pcInd;
}
public void setPcInd(String pcInd)
{
this.pcInd = pcInd;
}
public String getRatingEffectiveDate()
{
return ratingEffectiveDate;
}
public void setRatingEffectiveDate(AdvancedDate ratingEffectiveDate)
{
if(ratingEffectiveDate != null)
{
this.ratingEffectiveDate = ratingEffectiveDate.toFormattedStringMMDDYYYY();
}
else
{
this.ratingEffectiveDate = new AdvancedDate().toFormattedStringMMDDYYYY();
}
}
public String getCompanyName()
{
return companyName;
}
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
public DtoType getType()
{
return hasGetCoveragesCoverageDTO() ? DtoType.GET_COVERAGE_POLICY : DtoType.RATE_POLICY;
}
public boolean hasGetCoveragesCoverageDTO()
{
if(lobDTOs != null)
{
for(ILineOfBusinessDTO lineDTO : lobDTOs)
{
if(lineDTO.hasGetCoveragesCoverageDTO())
{
return true;
}
}
}
return false;
}
#Override
public void addLob(ILineOfBusinessDTO lob) {
lobDTOs.add(lob);
}
#Override
public Iterator<ILineOfBusinessDTO> getLobIterator() {
return lobDTOs.iterator();
}
public ICoverageDTO findCoverage(String coverageID)
{
ICoverageDTO coverageDTO = null;
for(ILineOfBusinessDTO lineDTO : lobDTOs)
{
coverageDTO = lineDTO.findCoverage(coverageID);
if(coverageDTO != null)
{
return coverageDTO;
}
}
return null;
}
#Override
public String toString()
{
return JSONConversionUtility.convertPolicyDTO(this);
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result
+ ((companyName == null) ? 0 : companyName.hashCode());
result = prime * result + ((lobDTOs == null) ? 0 : lobDTOs.hashCode());
result = prime * result + ((pcInd == null) ? 0 : pcInd.hashCode());
result = prime
* result
+ ((ratingEffectiveDate == null) ? 0 : ratingEffectiveDate
.hashCode());
return result;
}
#Override
public boolean equals(Object object)
{
if(object instanceof PolicyDTO)
{
return object.toString().equals(this.toString());
}
return false;
}
}
Your PolicyDTO class has hashCode inconsistent with equals - it violates the following rule:
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce
the same integer result.
Cache uses hashCode (much like HashMap class does), so when it sees two keys with different hashcodes, it assumes they are not equal.
This question already has answers here:
HashMap to return default value for non-found keys?
(16 answers)
Closed 9 years ago.
While using Map as a function argument, only values for 3 keys are populated. However when this function is invoked in another function, the user populates values for initial 2 keys and he does not require 3rd key to be assigned with any value. However if 3rd key is not assigned any value then, the 3rd key is display null value.
Is there any way to avoid this. if user does not assign any value to 3rd key, it must be empty instead of null value.
public String setMapValues(Map<String,String> testMap) throws Exception
{
String str="";
str= testMap.get("a");
str+=testMap.get("b");
str+=testMap.get("c");
info(str);
return str;
}
public void run() throws Exception
{
LinkedHashMap<String,String> myMap = new LinkedHashMap<String,String>();
myMap.put("a", "James");
myMap.put("b", "Bond");
this.setMapValues(myMap);
}
The function calls displays JamesBondnull as the output, instead it should only display JamesBond as the output by ignoring/skipping the null at the end.
You can use a function like
static String nullAsEmpty(Object o) {
return o == null ? "" : o.toString();
}
public String setMapValues(Map<String,String> testMap) {
String str = nullAsEmpty(testMap.get("a")) +
nullAsEmpty(testMap.get("b")) +
nullAsEmpty(testMap.get("c"));
info(str);
return str;
}
How about:
String temp = testMap.get("c");
str+= (temp == null : "" : temp);
You can implement your version of Map:
import java.util.HashMap;
class MyMap<K, V> extends HashMap<K, V> {
#Override
public V get(Object key) {
V val = super.get(key);
if (val != null) {
return val;
} else {
return "";
}
}
}
Then just use MyMap instead of Map
Or init your map with default values, if you know all keys which could be null
Map getInstance(){
Map<String,String> myMap = new LinkedHashMap<String,String>();
myMap.put("a", "");
myMap.put("b", "");
myMap.put("b", "");
return myMap;
}
By putting duplicate keys the old values are replaced by the new ones.
To be complete:
If you use Vadchens answer - which is better - you can do two things:
Extends your map by setting generic value-parameter directly to String
class MySecMap<K> extends LinkedHashMap<K, String>{
#Override
public String get(Object key) {
String val = super.get(key);
if (val != null) {
return val;
} else {
return "";
}
}
}
Or create a class with an extra interface and a default-value-provider:
interface IDefaultValueProvider<V>{
V getDefaultValue();
}
class MyMap<K, V, D extends IDefaultValueProvider<V>> extends LinkedHashMap<K, V>{
private IDefaultValueProvider<V> provider;
public MyMap(IDefaultValueProvider<V> p){
super();
provider = p;
}
#Override
public V get(Object key) {
V val = super.get(key);
if (val != null) {
return val;
} else {
return this.provider.getDefaultValue();
}
}
}
I'm trying to create a program which contains a generic method, which contains a type parameter. It should return an instance of the class Pair. I'm not sure how i can return a Pair. The code i have is below:
public class MinMaxArray
{
public static <ArrayType extends Comparable<ArrayType>>
ArrayType getMinMax(ArrayType[] anArray)
throws IllegalArgumentException
{
try
{
ArrayType resultMin = anArray[0];
ArrayType resultMax = anArray[0];
for (int index = 1; index < anArray.length; index++)
if (result.compareTo(anArray[index]) < 0)
result = anArray[index];
if (result.compareTo(anArray[index]) > 0)
result = anArray[index];
return resultMin;
return resultMax;
}//try
catch (ArrayIndexOutOfBoundsException e)
{ throw new IllegalArgumentException("Array must be non-empty", e); }
catch (NullPointerException e)
{ throw new IllegalArgumentException("Array must exist", e); }
}//getMinMax
}//class MinMaxArray
Pair class Code:
//Two onjects grouped into a pair.
public class Pair<FirstType, SecondType>
{
//The first object.
private final FirstType first;
//The second object.
private final SecondType second;
//Constructor is given the two objects.
public Pair(FirstType requiredFirst, SecondType requiredSecond)
{
first = requiredFirst;
second = requiredSecond;
}//Pair
//Return the first object.
public FirstType getFirst()
{
return first;
}//GetFirst
//Return the second object.
public SecondType getSecond()
{
return second;
}//GetSecond
}//class Pair
I'm not sure how i can get the resultMax and resultMin to return as a Pair. Thanks for the help.
Perhaps,
public static <ArrayType extends Comparable<ArrayType>>
Pair<ArrayType, ArrayType> getMinMax(ArrayType[] anArray) {
...
return new Pair<ArrayType, ArrayType>(resultMin, resultMax);
}
try
return new Pair<ArrayType, ArrayType>(resultMin, resultMax);
IMHO I would use
return new ArrayType[] { resultMin, resultMax };
or you could add a factory method to Pair class
public static <FirstType, SecondType> Pair<FirstType, SecondType> of(FirstType first, SecondType second) {
return new Pair<FirstType, SecondType>(first, second);
}
then you can write
return Pair.of(resultMin, resultMax);