Java-8 - sort keys of Map - java-8

I have this Java Map:
Map<ScheduleAbsenceHeaderHistoryTypeEnum, ValueObject>
....
public enum ScheduleAbsenceHeaderHistoryTypeEnum {
ADDITIONAL_HOURS("ADDITIONAL_HOURS"),
HOLIDAY("HOLIDAY"),
REMAINING_HOLIDAY_HOURS("REMAINING_HOLIDAY_HOURS"),
REMAINING_HOLIDAY_DAYS("REMAINING_HOLIDAY_DAYS"),
TRANSFER_HOLIDAY("TRANSFER_HOLIDAY"),
INCREMENT_HOLIDAY("INCREMENT_HOLIDAY"),
..
and I will sort the keys of the map alphabetically.
Is there a possibility to do this in a simple way?

You can create a map sorted by the enum’s name like
Map<ScheduleAbsenceHeaderHistoryTypeEnum, ValueObject> map
= new TreeMap<>(Comparator.comparing(Enum::name));
This uses the constant name as declared in the enum class, e.g.
enum ScheduleAbsenceHeaderHistoryTypeEnum {
ADDITIONAL_HOURS, HOLIDAY, REMAINING_HOLIDAY_HOURS,
REMAINING_HOLIDAY_DAYS, TRANSFER_HOLIDAY, INCREMENT_HOLIDAY,
}
There is no need to specify that name manually.
But if you have a property that might be different from the name, you may use
Map<ScheduleAbsenceHeaderHistoryTypeEnum, ValueObject> map
=new TreeMap<>(Comparator.comparing(ScheduleAbsenceHeaderHistoryTypeEnum::getProperty));
to sort by that specific property.

Given Map<ScheduleAbsenceHeaderHistoryTypeEnum, ValueObject> map:
map.keySet().stream()
.sorted(Comparator.comparing(ScheduleAbsenceHeaderHistoryTypeEnum::getName))
.collect(Collectors.toList());
will produce a sorted List<ScheduleAbsenceHeaderHistoryTypeEnum>.
Edit:
If you like to get a Map which has its keys sorted while you put elements into it use something like this:
SortedMap<ScheduleAbsenceHeaderHistoryTypeEnum, ValueObject> map =
new TreeMap<ScheduleAbsenceHeaderHistoryTypeEnum, ValueObject>(comparing(ScheduleAbsenceHeaderHistoryTypeEnum::getName)) {{
put(HOLIDAY, null);
put(REMAINING_HOLIDAY_DAYS, null);
put(TRANSFER_HOLIDAY, null);
put(INCREMENT_HOLIDAY, null);
put(ADDITIONAL_HOURS, null);
}};
The statement:
map.keySet().forEach(System.out::println);
will produce the following output:
ADDITIONAL_HOURS
HOLIDAY
INCREMENT_HOLIDAY
REMAINING_HOLIDAY_DAYS
TRANSFER_HOLIDAY

Related

Java 8 stream compare two objects and run a function on them

I've a a stream which I want to partition into smaller parts based on matching Id and then apply some proccessing logic on each of the part/element.
class BigRequest{
String bId;
List<Parts> parts;
//getters and setter here
}
Class Parts{
String pId;
String partId;
//getters and setter here
}
I want to segregate and create a list of Parts of size 10 when the partId of different parts are same.
How to use the filter or reduce or groupingBy function to compare the two elements and put them to a list?
I've tried filter like below, doesn't take p1 variable:
big.stream().filter( p -> p.getPartId() == p1.getPartId()) //error
Tried groupingBy like this
big.stream().collect(Collectors.groupingBy(Parts::getPartId) //error
I want to iterate over the filtered/reduced list a another and call another function called abc(). How can I do it using Java Streams?
pseudo:
big.getParts().stream.
//dividing logic logic
for(i < parts.size)
abc(p)
Thanks
You might use something like this:
Map<String,List<Parts>> commonId = big.getParts().
stream().
collect(
Collectors.groupingBy(
Parts::getPartId,
Collectors.mapping(
Function.identity(),
Collectors.toList()
)
)
);
and after it, you will just need to iterate over the map and apply your function.
commonId.entrySet().stream().map(entry -> apply(entry))...
Updated
We can omit Collectors.mapping(Function.identity(),Collectors.toList()) part, since it is a default behaviour of groupingBy
Map<String,List<Parts>> commonId = big.getParts().
stream().
collect(
Collectors.groupingBy(
Parts::getPartId
)
);

How to sort a list of strings by using the order of the items in another list?

I want to sort a list of strings (with possibly duplicate entries) by using as ordering reference the order of the entries in another list. So, the following list is the list I want to sort
List<String> list = ['apple','pear','apple','x','x','orange','x','pear'];
And the list that specifies the order is
List<String> order = ['orange','apple','x','pear'];
And the output should be
List<String> result = ['orange','apple','apple','x','x','x','pear','pear'];
Is there a clean way of doing this?
I don't understand if I can use list's sort and compare with the following problem. I tried using map, iterable, intersection, etc.
There might be a more efficient way but at least you get the desired result:
main() {
List<String> list = ['apple','pear','apple','x','x','orange','x','pear'];
List<String> order = ['orange','apple','x','pear'];
list.sort((a, b) => order.indexOf(a).compareTo(order.indexOf(b)));
print(list);
}
Try it on DartPad
The closure passed to list.sort(...) is a custom comparer which instead of comparing the passed item, compares their position in order and returns the result.
Using a map for better lookup performance:
main() {
List<String> list = ['apple','pear','apple','x','x','orange','x','pear'];
List<String> orderList = ['orange','apple','x','pear'];
Map<String,int> order = new Map.fromIterable(
orderList, key: (key) => key, value: (key) => orderList.indexOf(key));
list.sort((a, b) => order[a].compareTo(order[b]));
print(list);
}
Try it on DartPad

Data structure: Two maps that point to the same value

I am looking for a data structure where multiple maps point to the same value
For example:
We have an object A
We have two maps Map1 and Map2
var map1 = {
objectA.attribute1: objectA
}
var map2 = {
objectA.attribute2: objectA
}
Now, if I delete the object from one map, it should also delete it in the other map.
var attribute1 = objectA.attribute1
var attribute2 = objectA.attribute2
delete map1[attribute1]
map2[attribute2] === null
In other words, there are multiple ways to look up an object but once it is deleted all the look ups are gone as well.
An alternative way to look at this problem might be:
This is a SQL like row based data structure.
We have an array of objects. Certain attributes in the object can be looked up in a map-like fashion. And the object can be deleted by any of the attributes.
Is there a data structure that will help me do this?
you should use a two way hash. one map keys to object the other maps objects to keys.
to add an object by key1,key2,...keyN :
insert the object to the first map by the list of keys and add the list of keys to the map by the object, where usually you would use a hash of the object for this purpose.
var map_by_key = { 'key1' : objectA , 'key2' : objectA , ... 'keyN' : objectA }
var map_by_object = { objectA_hash : [ 'key1' , 'key2' , ... , 'keyN' ] }
to remove an object by key:
get the object by the key from the first map then get the list of keys from object hash from the second map. removing all keys from the first map and lastly remove the key from the second map.

How to remove from an List Object in c#

I have an Action method in my controller which returns a List Object
Public ActionResult GetCats(long Id,string strsortorder,string dltIds)
{
var Result=objrepo.GetCats(Id);//this method returns me List of Result
}
My array looks like this:
var Result=[{CatId:1015,CatName:Abc},{CatId:1016,CatName:Acd},
{CatId:1017,CatName:Adf},{CatId:1018,CatName:CDdf},{CatId:1019,CatName:asdas},
{CatId:1020,CatName:Abc},{CatId:1021,CatName:Abc},{CatId:1022,CatName:Abc},
{CatId:1023,CatName:Abc},{CatId:1024,CatName:Abc}]
What I want to do is:
Using two more parameters in my Action Method "strsortorder" and "dltIds"
that have a list of ids like this:
strsortorder="1021,1015,1016,1019,1022";
dltIds="1017,1018,1020";
From this the "Result" returned from my method , I want to remove the records which are in "dltids" and the remaining array should be sorted in the order which I have in "strsortorder";
In the end the new object should look like this:
var NewResult=[{CatId:1021,CatName:Abc},{CatId:1015,CatName:Abc},
{CatId:1016,CatName:Acd},{CatId:1019,CatName:asdas},{CatId:1022,CatName:Abc},
{CatId:1023,CatName:Abc},{CatId:1024,CatName:Abc}]
Can any one help me in acheiving this in linq or any other way?
I want to avoid any type of loop or froeach here for max extent, I know it can be done by looping but I want to avoid this since the result can sometimes contain large amounts of data.
I realized you can use an ArrayList instead of a Dictionary and it would be faster. I think Dictionary is clear how it works but here is the "better" implementation using array list:
var excludeList = dltIds.Split(",".ToCharArray());
ArrayList sortList = new ArrayList(strsortorder.Split(",".ToCharArray()));
var NewResult =
Result.Where(item => ! excludeList.Contains(item.CatId.ToString()))
.OrderBy(item => {
if (sortList.Contains(item.CatId.ToString()))
return sortList.IndexOf(item.CatId.ToString());
return sortList.Count;
});
Original answer below:
Public ActionResult GetCats(long Id,string strsortorder,string dltIds)
{
var Result=objrepo.GetCats(Id);//this method returns me List of Result
var excludeList = dltIds.Split(",".ToCharArray());
int orderCount = 0; // used in the closure creating the Dictionary below
var sortList = strsortorder.Split(",".ToCharArray())
.ToDictionary(x => x,x => orderCount++);
// filter
var NewResult =
Result.Where(item => ! excludeList.Contains(item.CatId.ToString()))
.OrderBy(item => {
if (sortList.ContainsKey(item.CatId.ToString()))
return sortList[item.CatId.ToString()];
return sortList.Count();
});
}
How this works:
First I create lists out of your comma separated exclude list using split.
This I create a dictionary with the key being the ordering ID and the value being an integer that goes up by one.
For the filtering I look to see if an item is in the exclude array before I continue processing the item.
I then do a sort on matching against the key and the dictionary and returning the value -- this will sort things in the order of the list since I incremented a counter when creating the values. If an item is not in the dictionary I return one more than the maximum value in the dictionary which must be the count of the items. (I could have used the current value of orderCount instead.)
Questions?

How do I use LINQ to obtain a unique list of properties from a list of objects?

I'm trying to use LINQ to return a list of ids given a list of objects where the id is a property. I'd like to be able to do this without looping through each object and pulling out the unique ids that I find.
I have a list of objects of type MyClass and one of the properties of this class is an ID.
public class MyClass
{
public int ID { get; set; }
}
I want to write a LINQ query to return me a list of those Ids.
How do I do that, given an IList<MyClass> such that it returns an IEnumerable<int> of the ids?
I'm sure it must be possible to do it in one or two lines using LINQ rather than looping through each item in the MyClass list and adding the unique values into a list.
IEnumerable<int> ids = list.Select(x=>x.ID).Distinct();
Use the Distinct operator:
var idList = yourList.Select(x=> x.ID).Distinct();
Using straight LINQ, with the Distinct() extension:
var idList = (from x in yourList select x.ID).Distinct();
When taking Distinct, we have to cast into IEnumerable too. If the list is <T> model, it means you need to write code like this:
IEnumerable<T> ids = list.Select(x => x).Distinct();
int[] numbers = {1,2,3,4,5,3,6,4,7,8,9,1,0 };
var nonRepeats = (from n in numbers select n).Distinct();
foreach (var d in nonRepeats)
{
Response.Write(d);
}
Output
1234567890

Resources