Is it possible to sort a List interface with object of ArrayList()?
List</*classname*/> list = new ArrayList<>();
I'm using application.properties of Spring boot to set the value in List interface
ModuleNames.java
public class ModuleNames {
private String moduleId;
private String moduleName;
//getters & setters.
}
Controller
#RequestMapping(value = "/getModuleNames", method = { RequestMethod.GET })
public #ResponseBody List<String> getModuleNames() {
List<ModuleNames> moduleNamesList = new ArrayList<>();
moduleNamesList.add(new ModuleNames("Country", env.getProperty("bulkUpload.location.country")));
moduleNamesList.add(new ModuleNames("State", env.getProperty("bulkUpload.location.state")));
moduleNamesList.add(new ModuleNames("City", env.getProperty("bulkUpload.location.city")));
moduleNamesList.add(new ModuleNames("Area Pincode", env.getProperty("bulkUpload.location.areaPincode")));
return moduleNamesList;
does anybody know how to sort the list.
I've tried
moduleNamesList.sort(Comparator.naturalOrder());
Collections.sort(moduleNamesList);
but both doesn't seem to work. Please help me here
You need to write your custom comparator for ModuleNames object, because Java doesn't know how to sort it as it is not a primitive type.
For example:
Collections.sort(moduleNamesList, new Comparator<ModuleNames>() {
#Override
public int compare(ModuleNames o1, ModuleNames o2) {
return o1.getModuleId().compareTo(o2.getModuleId());
}
});
or
moduleNamesList.sort(new Comparator<ModuleNames>() {
#Override
public int compare(ModuleNames o1, ModuleNames o2) {
return o1.getModuleName().compareTo(o2.getModuleName());
}
});
You can avoid defining the comparison logic by using an instance method reference and the Comparator.comparing method – which extracts and creates a Comparable based on that function.
We're going to use the getters to build the Lambda expression.
sort the list by moduleName:
moduleNamesList.sort(Comparator.comparing(ModuleNames::getModuleName));
sort the list by moduleName in reverse order:
moduleNamesList.sort(Comparator.comparing(ModuleNames::getModuleName).reversed());
sort the list by first moduleName and then moduleId:
moduleNamesList.sort(Comparator.comparing(ModuleNames::getModuleName).thenComparing(ModuleNames::getModuleId));
You can also use custom comparator:Use This Reference
moduleNamesList.sort(Comparator.comparing(ModuleNames::getName));
moduleNamesList.sort(Comparator.comparing(mn -> mn.name));
Or even more sorted:
moduleNamesList.sort(Comparator.comparing(ModuleNames::getName)
.thenComparing(ModuleNames::getId));
Related
so I have seen some similar questions to this but have been unable to apply their answers to my code and am wondering how to do this. So basically I have the following code (simplified):
public Map<String, List<String>> myFunction(String myApp) {
List<String> myIds = myService.getIds(myApp);
return myIds.stream()
.map(id -> {
final List<String> myObjects = myService.getListForId(id);
return new MyWrapper(id, myObjects);
}).collect(Collectors.toMap(a -> a.ID, a -> a.OBJECTS);
}
class MyWrapper {
public final String ID;
public final List<String> OBJECTS;
public MyWrapper(String id, List<String> objects) {
ID = id;
OBJECTS = objects;
}
}
I can't figure out how to access id in the Collectors function since the list has no gettable relation to the id so I created a wrapper class to store both values. Any ideas on a way to do this without the wrapper? Thanks
streams the ids via myService.getIds
then simply maps those ids to the list returned by the service (using a method reference).
Map<String, List<String>> map = myService.getIds(myApp).
stream().collect(Collectors.toMap(id->id, myService::getListForId));
I'm trying to implement a checked builder pattern similar to how it's described in this:
https://dev.to/schreiber_chris/creating-complex-objects-using-checked-builder-pattern
The result I'm trying to reach is as follows:
Builder builder = new Builder('TestVal')
.when('this').then(new Set<String> {'val1','val2'})
.when('that').then(new Set<String> {'val3','val4'});
And the resulting object would contain a collection with any number of whens with the associted thens
e.g. a Map like this (the param for when() is unique):
'this' => ['val1','val2'],
'that' => ['val3','val4']
I'm struggling with a couple things:
How to associate the values passed into then() with the value
passed into when()
How to require then() be called after
when(). (e.g. - .when('this').when('that') //invalid
The easiest way is to use multiple interfaces to enforce your call ordering and then use that knowledge to associate your items. For example, something along these lines:
interface Then{
When then(Set<String> values);
}
interface When{
Then when(String condition);
}
class Builder implements When, Then{
public static When create(){ return new Builder(); }
private Map<String, Set<String>> storedMappings = new HashMap<>();
private String currentCondition;
private Builder(){ }
public Then when(String condition){
currentCondition = condition;
return this;
}
public When then(Set<String> values){
storedMappings.put(currentCondition, values);
return this;
}
}
I am trying to split String values based on de-limiter and trim them before putting them in a list.
I am able to split the values, could you please suggest how can be trim the list.
#Value("#{'${string-values}'.split(',')}")
private List<String> textList;
The problem it seems is, Split returns a list and I need to invoke trim() before storing them in the variable.
Check
Java - Split and trim in one shot
#Value("#{'${string-values}'.split('\\s*,\\s*')}")
private List<String> textList;
Better to provide no space between values in properties file.
To put a check in code it can be done in this way.
private List<String> textList;
public YourController(#Value("${string-values}") String propertyFromFile) {
this.textList = new ArrayList<>();
Arrays.asList(propertyFromFile.split(",")).forEach(b-> this.textList.add(b.trim()));
}
I think it may be better to use #Configuration and then process that instead of doing like this, however you can add a new annotation on top of value annotation and use that annotation to process the list. For example
#Target(value = {ElementType.TYPE})
#Value
public #interface Trim {
//Override the method you want to override
}
Public TrimPricessor {
//Implement the annotation method here
}
Since you are using Spring Boot, use:
#Component
#ConfigurationProperties(prefix = "foo.bar")
public class MyConfig {
private List<String> list = new ArrayList<>();
public List<String> getList() {
return this.list;
}
public void setList(List<String> list) {
this.list = list;
}
}
foo.bar.list= a , b, c
The list entries are trimmed.
We are working with mvc design pattern, where all the data is stored under map.
I want to iterate over all the classes in the system and for each to check what the method is putting on the map and what does the method get from the map.
For example for the next code:
private void myFunc()
{
Object obj = model.get("mykey");
Object obj2 = model.get("mykey2");
.....
model.put("mykey3", "aaa");
}
I want to know that in this function we have 2 gets: mykey and mykey2 and 1 put: mykey3
How can I do it with the code.
Thanks.
You tagged this with "reflection", but that will not work. Reflection only allows you to inspect "signatures". You can use it to identify the methods of a class, and the arguments of the methods.
It absolutely doesn't help you to identify what each method is doing.
In order to find out about that, you would need to either parse the java source code side, or byte code classes. As in: write code that reads that content, and understands "enough" of it to find such places. Which is a very challenging effort. And of course: it is very easy to bypass all such "scanner" code, by doing things such as:
List<String> keysToUpdate = Arrays.asList("key1", "key2");
for (String key : keysToUpdate) {
... does something about each key
Bang. How would you ever write code that reliable finds the keys for that?
When you found that code, now imagine that the list isn't instantiated there, but far away, and past as argument? When you figured how to solve that, now consider code that uses reflection to acquire the model object, and calls method on that. See? For any "scanner" that you write down, there will be ways to make that fail.
Thus the real answer is that you are already going down the wrong rabbit hole:
You should never have written:
Object obj = model.get("mykey");
but something like
Object obj = model.get(SOME_CONSTANT_FOR_KEY_X);
Meaning: there is no good way to control such stuff. The best you can do is to make sure that all keys are constants, coming from a central place. Because then you can at least go in, and for each key in that list of constants, you can have your IDE tell you about their usage.
NOTES
I assumed that your situation is complicated enough that simple or advanced text search in codebase doesn't help you.
This is a hack not a generic solution, designed only for testing and diagnosis purposes.
To use this hack, you must be able to change your code and replace the actual model with the proxy instance while you're testing/diagnosing. If you can't do this, then you have to use an even more advanced hack, i.e. byte-code engineering with BCEL, ASM, etc.
Dynamic proxies have drawbacks on code performance, therefore not an ideal choice for production mode.
Using map for storing model is not a good idea. Instead a well-defined type system, i.e. Java classes, should be used.
A general design pattern for a problem like this is proxy. An intermediate object between your actual model and the caller that can intercept the calls, collect statistics, or even interfere with the original call. The proxied model ultimately sends everything to the actual model.
An obvious proxy is to simply wrap the actual model into another map, e.g.
public class MapProxy<K, V> implements Map<K, V> {
public MapProxy(final Map<K, V> actual) {
}
// implement ALL methods and redirect them to the actual model
}
Now, reflection doesn't help you with this directly, but can help with implementing a proxy faster using dynamic proxies (Dynamic Proxy Classes), e.g.
#SuppressWarnings("unchecked")
private Map<String, Object> proxy(final Map<String, Object> model) {
final InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Collect usage stats or intervene
return method.invoke(model, args);
}
};
return (Map<String, Object>) Proxy.newProxyInstance(Map.class.getClassLoader(),
new Class<?>[] { Map.class }, handler);
}
NOTE: Either case you need to be able to replace the actual model with the proxied model at least for the duration of your test.
With another trick, you can find out who called which method of your model. Simply by accessing Thread.currentThread().getStackTrace() and retrieving the appropriate element.
Now puting all the pieces together:
InvocationLog.java
public final class InvocationLog {
private Method method;
private Object[] arguments;
private StackTraceElement caller;
public InvocationLog(Method method, Object[] arguments, StackTraceElement caller) {
this.method = method;
this.arguments = arguments;
this.caller = caller;
}
public Method getMethod() { return this.method; }
public Object[] getArguments() { return this.arguments; }
public StackTraceElement getCaller() { return this.caller; }
#Override
public String toString() {
return String.format("%s (%s): %s",
method == null ? "<init>" : method.getName(),
arguments == null ? "" : Arrays.toString(arguments),
caller == null ? "" : caller.toString());
}
}
ModelWatch.java
public final class ModelWatch {
private final Map<String, Object> modelProxy;
private final List<InvocationLog> logs = new ArrayList<>();
public ModelWatch(final Map<String, Object> model) {
modelProxy = proxy(model);
}
#SuppressWarnings("unchecked")
private Map<String, Object> proxy(final Map<String, Object> model) {
final InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method, args, Thread.currentThread().getStackTrace());
return method.invoke(model, args);
}
};
return (Map<String, Object>) Proxy.newProxyInstance(Map.class.getClassLoader(),
new Class<?>[] { Map.class }, handler);
}
private void log(Method method, Object[] arguments, StackTraceElement[] stack) {
logs.add(new InvocationLog(method, arguments, stack[3]));
// 0: Thread.getStackTrace
// 1: InvocationHandler.invoke
// 2: <Proxy>
// 3: <Caller>
}
public Map<String, Object> getModelProxy() { return modelProxy; }
public List<InvocationLog> getLogs() { return logs; }
}
To put it in use:
private Map<String, Object> actualModel = new HashMap<String, Object>();
private ModelWatch modelWatch = new ModelWatch(model);
private Map<String, Object> model = modelWatch.getModelProxy();
// Calls to model ...
modelWatch.getLogs() // Retrieve model activity
I need strict compliance with the order of the elements in my xml document. If I use XmlHttpContent serializer to form xml content, fields sort alphabetically.
Is there any way to specify explicitly order of the elements in xml? Or are there other ways to create and post http requests with the xml body?
I know this answer isn't ideal but I recently came across this issue when trying to use the http client library for serialisation to xml. The solution I've found that works is to have my DTO classes provide a method to convert them into a sorted map of some kind.
In my case this is an ImmutableMap<String, Object> as I'm also using Guava but any map with controllable order will do. The basic idea is to work with the java objects to construct your data but then when the time comes to serialise them you serialise the map instead.
public interface OrderedXml {
ImmutableMap<String, Object> toOrderedMap();
}
public class Parent implements OrderedXml {
#Key("First") String first;
#Key("Second") String second;
#Key("Child") Child third;
#Override
public ImmutableMap<String, Object> toOrderedMap() {
return ImmutableMap.of(
// the order of elements in this map will be the order they are serialised
"First", first,
"Second", second,
"Child", third.toOrderedMap()
);
}
}
public class Child implements OrderedXml {
#Key("#param1") String param1;
#Key("#param2") String param2;
#Key("text()") String value;
#Override
public ImmutableMap<String, Object> toOrderedMap() {
return ImmutableMap.of(
// the same goes for attributes, these will appear in this order
"#param1", param1,
"#param2", param2,
"text()", value
);
}
}
public class Main {
public static void main(String[] args) {
// make the objects
Parent parent = new Parent();
parent.first = "Hello";
parent.second = "World";
parent.child = new Child();
parent.child.param1 = "p1";
parent.child.param2 = "p2";
parent.child.value = "This is a child";
// serialise the object to xml
String xml = new XmlNamespaceDictionary()
.toStringOf("Parent", parent.toOrderedXml()); // the important part
System.out.println(xml); // should have the correct order
}
}
I know this solution isn't ideal but at least you can reuse the toOrderedXml to make a nice toString :-).