Priority Queue of user defined objects - java

I wanna create priority queue of objects according to their attributes. how can I compare the queue according to spesific attributes. for example if i type somewhere id, queue is designed for id. i have two different java file below. I wanna get all possible queues by comparing attributes of objects.
first
public class customers {
int id;
String name;
int age;
double money;
public customers(int id, String name, int age, double money) {
this.id = id;
this.name = name;
this.age = age;
this.money = money;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
main file starts now
import java.util.ArrayList;
import java.util.PriorityQueue;
public class draft {
public static void main(String[] args) {
PriorityQueue<customers> customerList= new PriorityQueue<>();
customers customer1= new customers(0,"jack",30,180.5);
customers customer2= new customers(1,"john",52,800.3);
customers customer3= new customers(2,"alice", 41, 400.5);
customerList.add(customer1);
customerList.add(customer2);
customerList.add(customer3);
for (customers c:customerList
) {
System.out.println(c.getId());
}
}
}
I want a simple solution like this. the code below is not valid but i can not understand complex codes. and i think there has to be a simple solution as this.
PriorityQueue<customers> customerList= new PriorityQueue<>(customers.age);
i do not know if i explained the question. for example if i compare objects id, the queue should be object#0,object#1,object#2 in this order. if i compare objects's age the queue will be object#0, object#2,object#1

Here are few ways to maintain a PriorityQueue based on any field of a particular class.
Below is an illustration to define a PriorityQueue sorted according to the field id (sorted in ascending order):
public static void main(String[] args)
{
// Method 1] Using Custom Comparator
PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getId));
Customers customer1 = new Customers(0,"jack",30,180.5);
Customers customer2 = new Customers(1,"john",52,800.3);
Customers customer3 = new Customers(2,"alice", 41, 400.5);
pq1.add(customer1);
pq1.add(customer2);
pq1.add(customer3);
// Method 2] Using Lambda Operator
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> x.id-y.id);
//Method 3] Custom Comparator again
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
{
#Override
public int compare(Customers a, Customers b)
{
return a.id-b.id;
}
});
pq2.addAll(pq1);
pq3.addAll(pq1);
System.out.println(pq1);
System.out.println(pq2);
System.out.println(pq3);
}
Output:
[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)]
[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)]
[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)]
Similarly you can design other queues based on any field of your choice.
To maintain the priority queue in reverse order (Decreasing/Descending order), we need to reverse the orders in the comprators like:
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> y.id-x.id);
Please note, for ascending it was: (x, y) -> x.id-y.id
for descending it will be: (x, y) -> y.id-x.id
Using custom Comparator:
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
{
#Override
public int compare(Customers a, Customers b)
{
return b.id-a.id; // reversed
}
});
And if you want to sort the priority queue based on two fields, let say age & id in such a way that if multiple age's are equal, then priority is given to id.
You can achieve the above in the following ways:
public static void main(String[] args)
{
// Method 1] Using Custom Comparator (Increasing order)
PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getAge).thenComparing(Customers::getId));
Customers customer1 = new Customers(0,"jack",30,180.5);
Customers customer2 = new Customers(1,"john",52,800.3);
Customers customer3 = new Customers(2,"alice", 41, 400.5);
pq1.add(customer1);
pq1.add(customer2);
pq1.add(customer3);
// Method 2] Using Lambda Operator (Increasing order)
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> (x.age == y.age) ? x.id-y.id : x.age-y.age);
//Method 3] Custom Comparator again (Reverse order)
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
{
#Override
public int compare(Customers a, Customers b)
{
return (a.age == b.age) ? b.id-a.id : b.age-a.age;
}
});
pq2.addAll(pq1);
pq3.addAll(pq1);
System.out.println(pq1);
System.out.println(pq2);
System.out.println(pq3);
}
For sorting based on age & money, few modifications are required as money is of double dataType. Below is how you can achieve the desired:
PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getAge).thenComparing(Customers::getMoney));
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> (x.age == y.age) ? Double.compare(x.money,y.money) : x.age-y.age);
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
{ #Override
public int compare(Customers a, Customers b)
{
return (a.age == b.age) ? Double.compare(a.money,b.money) : a.age-b.age;
}
});
Use the poll method to verify the order of elements in the priorityQueue.
All the implementations are easy to understand. But if you are having a tough time understanding it, please reach out.

The way to do this would be to use multiple Comparator classes. Comparator gives us a way to define HOW we want our objects to be compared to each other - in your case, it could be id,age etc.
public class Comparator<Customer> CustomerAgeComparator implements Comparator<Customer>() {
public int compare(Customer user1, Customer user2) {
int userPoints1 = user1.getAge();
int userPoints2 = user2.getAge();
if (userPoints1 == userPoints2)
return 0;
else if (userPoints1 > userPoints2)
return 1;
else
return -1;
}
};
The above comparator will sort customers in descending order of age.
Then you need to pass this information to your Priority Queue somehow. Luckily PriorityQueue has a constructor that allows one to do just that. Call it in the following manner :
PriorityQueue oldestCustomerFirst = PriorityQueue<String>(new CustomerAgeComparator);

Related

Sort List of Objects by values from array;

I have a List<Brand> categories; with 1000+ items.
For each item from the list I have id, to get that I use categories.getId();
And I have an array int[] sortedIdArr = {4,53,102,403,110,5,6,8,12};
I would like to sort my categories list and make order by id how it is in sortedIdArr.
How can I implement that ?
private void sortBrandsById(List<Brand> categories) {
Collections.sort(categories, new Comparator<Brand>() {
public int compare(Brand o1, Brand o2) {
}
});
}
Can I use Collections.sort ?
Typically you would use Collections.sort, or the equivalent idioms in Java 8 if applicable, or a sorted Collection such as TreeSet.
However in this case you want to follow a pre-defined order, dictated by your sortedIdArr array.
One way to achieve that is to use a linked collection (e.g. a LinkedHashSet).
Then you iterate your sortedIdArr array, and search your List<Brand> for an object with the given ID.
If found, you add the Brand object with the given ID to your LinkedHashSet, which will retain the insertion order.
Note that if an ID is not found, your Set will not exactly "match" the array.
Self-enclosed example, using Java 8
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class Main {
// simplified Brand pojo
static class Brand {
int id;
public Brand(int id) {
this.id = id;
}
public int getId() {
return id;
}
// for output clarity
#Override
public String toString() {
return String.format("Brand: %d", id);
}
}
public static void main(String[] args) throws Exception {
// simplified ID list
int[] sortedIdArr = {4,53,102};
// "randomly" ordered Brand list
final List<Brand> categories = new ArrayList<Brand>() {
{
add(new Brand(1));
add(new Brand(102));
add(new Brand(53));
add(new Brand(4));
add(new Brand(0));
}
};
// destination: linked set
Set<Brand> linked = new LinkedHashSet<Brand>();
// streaming the ID array in order
Arrays.stream(sortedIdArr)
.forEach((i) -> {
// retrieving a Brand with same ID as the current
// from the "randomly" ordered list
Optional<Brand> toAdd = categories.stream()
.filter((b) -> b.getId() == i)
.findFirst();
// making sure there's one
if (toAdd.isPresent()) {
// adding to linked set
linked.add(toAdd.get());
}
}
);
System.out.println(linked);
}
}
Output
[Brand: 4, Brand: 53, Brand: 102]
Imperative idiom for older Java versions
for (int i: sortedIdArr) {
for (Brand b: categories) {
// assuming no nulls
if (b.getId() == i) {
linked.add(b);
break;
}
}
}
Yes you can use the Collections.sort()
To sort your Brand using id :
public int compare(Brand o1, Brand o2) {
return o1.getId().compareTo(o2.getId());
}
To sort your Brand using the array of id sortedIdArr :
Implement the Comparator Class :
class C implements Comparator<A> {
int[] idOrder;
public C(int[] idOrder) {
super();
this.idOrder = idOrder;
}
#Override
public int compare(A o1, A o2) {
Integer indexofO1 = Arrays.binarySearch(idOrder, o1.getId());
Integer indexofO2 = Arrays.binarySearch(idOrder, o2.getId());
return indexofO1.compareTo(indexofO2);
}
}
The key idea here is to inverse the process and compare using the index of the id instead of the id itself !
To use it :
Collections.sort(list, new C (idOrder));
Test Example :
int[] idOrder = new int [] {3,1,2};
List<A> list = new ArrayList<>();
list.add(new A(1));
list.add(new A(2));
list.add(new A(3));
System.out.println(list);
//Output : [A [id=1], A [id=2], A [id=3]]
Collections.sort(list, new C(idOrder));
System.out.println(list);
//Output : [A [id=3], A [id=1], A [id=2]]
You can do it with Collections.sort(...) but I strongly recommend not to go for Comparator method in this situation with this number of items in your list.
You can have a loop on your List<Brand> categories and add them in a HashMap<Integer,Brand> named tempMap. Then use it for lookup them in the order of your sortedIdArr array. Change your sort method like this:
private void sortBrandsById(List<Brand> categories, int [] sortedIdArr) {
HashMap<Integer,Brand> tempMap = new HashMap<Integer, Brand>(categories.size());
for (int i = 0; i < categories.size(); i++) {
tempMap.put(categories.get(i).getId(), categories.get(i));
}
categories = new ArrayList<Brand>(sortedIdArr.length);
for (int i = 0; i < sortedIdArr.length; i++) {
categories.add(tempMap.get(sortedIdArr[i]));
}
}
This way of sorting is from order O(n) for creating the tempMap + O(n) for recreating the category list. Although, the O(1) is not guaranteed for HashMap's get/put operations, java's decent hashing implementation very good and reliable. So the total complexity can not be very greater than O(n). At least it is very better than O(n^2). Time complexity is very important and I don't think you can find a way better than something very near O(n) complexity.
Hope this would be helpful.
You can use the following code(You need the Apache commons lang jar-otherwise you have to iterate through your array to find the index).
private static void sortBrandsById(List<Brand> categories,int[] array) {
Collections.sort(categories, new Comparator<Brand>() {
public int compare(Brand o1, Brand o2) {
return ArrayUtils.indexOf(array,o1.getId())-ArrayUtils.indexOf(array,o2.getId());
}
});
}
If you are able to put your predefined sorting order in a list not in an array , it will be much easier.

How to create a summary of a list of objects?

I think it's a pretty basic question and there should be solutions out there, but I didn't manage to find any. I think I need more help in terminology, on what term I should look up to learn about my problem, but I really appreciate any help.
Anyway, I would like to implement the following:
I have a list of Objects. Each object is in the form of ExampleClass below:
public class ExampleClass {
private String name;
private Double firstDouble;
private Double secondDouble;
+ constructor and a bunch of methods
}
Basically I have a name variable and a bunch of numbers associated with each instance of ExampleClass. The name variable is not an id, so there may be several ExampleClasses in the list with the same name, all with different numbers associated with them. What I would like to do is to create a "summary" from this list:
Filtering out each instance of ExampleClass with the same name, so in my final list of objects, I do not have two objects with the same name variable.
I want to make operations with the Double variables of the objects with the same name.
So lets imagine I have the following ExampleClasses in my list:
ExampleClass first = new ExampleClass("apple",1,4);
ExampleClass second = new ExampleClass("pear",6,12);
ExampleClass third = new ExampleClass("apple",5,2);
ExampleClass fourth = new ExampleClass("peach",1,2);
ExampleClass fifth = new ExampleClass("plum",10,25);
In this case I want to remove from the list the first or third element, since they have the same name and I want to make an operation with the numbers, like adding up 1 and 5 and multiplying 4 and 2.
Thanks for any help in advance!
EDIT: I can solve it with a bunch of loops. However, I need my code to be readable and as efficient as it can get. I'm not looking for a brute force solution with nested loops, I'm interested if there is a nice, or nicer solution.
Finding the sum of all X values grouped by name is pretty easy in Java 8:
// Find the sum of X and group by name
Map<String, Integer> sumXByName = Stream.of(first, second, third, fourth, fifth)
.collect(groupingBy(ExampleClass::getName,
Collectors.<ExampleClass>summingInt(e -> e.getX())));
// Print the results
sumXByName.entrySet().stream()
.map(e -> e.getKey() + " -> " + e.getValue())
.forEach(System.out::println);
Prints:
plum -> 10
apple -> 6
pear -> 6
peach -> 1
However, finding the sum of X and product of Y requires a custom collector.
static class ExampleStatistics implements Consumer<ExampleClass> {
private Integer sum = 0;
private Integer product = null;
#Override
public void accept(ExampleClass value) {
sum += value.getX();
if (product == null) {
product = value.getY();
} else {
product *= value.getY();
}
}
public ExampleStatistics combine(ExampleStatistics other) {
sum += other.sum;
product *= other.product;
return this;
}
public Integer getSum() {
return sum;
}
public Integer getProduct() {
return product;
}
#Override
public String toString() {
return String.format("Sum X = %d, Product Y = %d", sum, product);
}
}
static class ExampleSummarizer
implements Collector<ExampleClass, ExampleStatistics, ExampleStatistics> {
#Override
public Supplier<ExampleStatistics> supplier() {
return ExampleStatistics::new;
}
#Override
public BiConsumer<ExampleStatistics, ExampleClass> accumulator() {
return (r, t) -> r.accept(t);
}
#Override
public BinaryOperator<ExampleStatistics> combiner() {
return (r, t) -> r.combine(t);
}
#Override
public Function<ExampleStatistics, ExampleStatistics> finisher() {
return i -> i; // identity finish
}
#Override
public Set<Collector.Characteristics> characteristics() {
return Stream.of(Characteristics.IDENTITY_FINISH, Characteristics.UNORDERED)
.collect(toSet());
}
};
Now you can easily summarize the objects:
// Summarize all examples and group by name
Map<String, ExampleStatistics> statsByName = Stream.of(first, second, third, fourth, fifth)
.collect(groupingBy(ExampleClass::getName, new ExampleSummarizer()));
Printing this map will yield the following:
plum -> Sum X = 10, Product Y = 25
apple -> Sum X = 6, Product Y = 8
pear -> Sum X = 6, Product Y = 12
peach -> Sum X = 1, Product Y = 2
EDIT: I used integers for convenience. However, there are summarizing equivalents available for doubles e.g. summingDouble.
class ExampleClass {
private final String name;
private final Integer x;
private final Integer y;
public ExampleClass(String name, Integer x, Integer y) {
super();
this.name = name;
this.x = x;
this.y = y;
}
public String getName() {
return name;
}
public Integer getX() {
return x;
}
public Integer getY() {
return y;
}
}
Filtering out each instance of ExampleClass with the same name, so in my final list of objects, I do not have two objects with the same name variable.
Consider making your class implement equals(Object obj) and Comparable interface or provides some means of creating a Comparator object.
Implement a SortedSet collection for your list such as TreeSet
I want to make operations with the Double variables of the objects
with the same name.
You could use the contains(Object obj) method provided by any Set inherited collection before adding an item to your list so that if the method returns true, you could do something with the duplicate. It is recommended that you keep your equals implementation consistent with your Comparable implementation.
Instead of
ExampleClass first = new ExampleClass("apple",1,4);
ExampleClass second = new ExampleClass("pear",6,12);
ExampleClass third = new ExampleClass("apple",5,2);
ExampleClass fourth = new ExampleClass("peach",1,2);
ExampleClass fifth = new ExampleClass("plum",10,25);
use List
List<ExampleClass> list = new ArrayList<>(5);
list.add(new ExampleClass("apple",1,4));
...
delete the first or third element
list.remove(1);
list.remove(3);
Other you can do by yourself, I think. You should just read about List, Map, Set and so on.

Sort list of objects using Collection.sort() with lambdas only

I am beginner in lambdas and trying to understand how it works. So I have this list of Student with id and score attributes and I have to sort it accoding to the score . My Code
import java.util.*;
class Student {
int id, score;
public Student(int id, int score) {
this.id = id;
this.score = score;
}
public String toString() {
return this.id + " " + this.score;
}
}
interface StudentFactory < S extends Student > {
S create(int id, int score);
}
class Test {
public static void main(String[] ad) {
StudentFactory < Student > studentFactory = Student::new;
Student person1 = studentFactory.create(1, 45);
Student person2 = studentFactory.create(2, 5);
Student person3 = studentFactory.create(3, 23);
List < Student > personList = Arrays.asList(person1, person2, person3);
// error in the below line
Collections.sort(personList, (a, b) -> (a.score).compareTo(b.score));
System.out.println(personList);
}
}
as you can see I tried Collections.sort(personList, (a, b) -> (a.score).compareTo(b.score)); it gave me error int cannot be dereferenced I know the error expected I just want to show what I wanted.
So is there any way to sort the Student object accoding to score using lambdas only?
I have also seen similar post where I found that List.sort or BeanComparator is the other option but is there any way I can do it with lambdas?
Thanks
(a, b) -> Integer.compare(a.score, b.score)
would work. int is not an object, it is a primitive, and you can't call int.compareTo, or any other methods on int.
Even better than that would be
Comparator.comparingInt(s -> s.score)
or, with a getter,
Comparator.comparingInt(Student::getScore)
And using List.sort doesn't make a difference as to whether or not you use lambdas or whatever. You just write personList.sort(Comparator.comparingInt(s -> s.score)) instead of Collections.sort(personList, Comparator.comparingInt(s -> s.score)).

Add Key and Value into an Priority Queue and Sort by Key in Java

I am trying to take in a List of strings and add them into a Priority Queue with Key and Value. The Key being the word and the value being the string value of the word. Then I need to sort the queue with the highest string value first. The priority queue is not letting me add 2 values.
public static List<String> pQSortStrings(List<String> strings) {
PriorityQueue<String, Integer> q = new PriorityQueue<>();
for (int x = 0; x < strings.size(); x++) {
q.add(strings.get(x),calculateStringValue(strings.get(x)));
}
return strings;
}
Problem
PriorityQueue can store a single object in it's each node. So what you are trying to do can not be done as it is.
But you can compose both objects in a single class and then use the PriorityQueue.
You would either need to supply a Comparator or rely on natural ordering by implementing Comparable interface.
Solution
Create a class which has String and int as it's members.
public class Entry {
private String key;
private int value;
// Constructors, getters etc.
}
Implement Comparable interface and delegate comparison to String.
public class Entry implements Comparable<Entry> {
private String key;
private int value;
public Entry(String key, int value) {
this.key = key;
this.value = value;
}
// getters
#Override
public int compareTo(Entry other) {
return this.getKey().compareTo(other.getKey());
}
}
Build the PriorityQueue using this class.
PriorityQueue<Entry> q = new PriorityQueue<>();
Add elements as following.
q.add(new Entry(strings.get(x), calculateStringValue(strings.get(x))));
Hope this helps.
Using Java-8
PriorityQueue<Map.Entry<String, Integer>> queue = new PriorityQueue<>(Map.Entry.comparingByValue(Comparator.reverseOrder()));
to add a new Entry
queue.offer(new AbstractMap.SimpleEntry<>("A", 10));
Solution
public static List<String> pQSortStrings(List<String> strings) {
Queue<String> pq = new PriorityQueue<>((a, b) ->
calculateStringValue(b) - calculateStringValue(a));
for (String str : strings) {
pq.add(str);
}
return strings;
}
Explanation
I believe that the cleanest way to do this is to store Strings in your pq and use a small custom Comparator.
In this case, we want to use calculateStringValue and the pq should return highest String values first. Therefore, make a pq of entries and use the following Comparator:
1 Queue<String> pq = new PriorityQueue<>(new Comparator<String>() {
2 #Override
3 public int compare(String a, String b) {
4 return calculateStringValue(b) - calculateStringValue(a);
5 }
6 });
7 for (String str : strings) {
8 pq.add(str);
9 }
10 return strings;
Simpler syntax for the Comparator, replacing lines 1 - 6, is:
Queue<String> pq = new PriorityQueue<>((a, b) ->
calculateStringValue(b) - calculateStringValue(a));
If you wanted to return smallest String values first, you could just switch the order around for a and b in the Comparator:
...new PriorityQueue<>((a, b) -> calculateStringValue(a) - calculateStringValue(b));
In general, the pattern a - b sorts by smallest first, and b - a sorts by largest values first.
Many good answers are already present but I am posting this answer because no one has used hashmap in their answers.
You can also make the priority Queue from HashMaps bellow is the example for the same. I am creating a max priority queue.
Mind well here I am considering that your hashmap contains only one Entry
PriorityQueue<HashMap<Character, Integer>> pq = new PriorityQueue<>((a, b) -> {
char keyInA = a.keySet().iterator().next(); // key of a
char keyInB = b.keySet().iterator().next(); // key of b
return b.get(keyInB) - a.get(keyInA);
});
For Insertion of the value in the priority queue.
pq.add(new HashMap<>() {
{
put('a', 0);
}
});
Define a class with a key field and a value field
Class MyClass{
int key;
String value
}
Queue<MyClass> queue = new PriorityQueue<>(Comparotor.comparingInt(a -> a.key));
Adding to #Tanmay Patil Answer, If you are using Java 8, You can use lambda for more concise code as comparator interface is a functional interface.
public class CustomEntry {
private String key;
private int value;
public CustomEntry(String key, int value) {
this.key = key;
this.value = value;
}
// getters etc.
}
Now below is the updated code
public static List<String> pQSortStrings(List<String> strings) {
PriorityQueue<CustomEntry> q = new PriorityQueue<>((x, y) -> {
// since you want to sort by highest value first
return Integer.compare(y.getValue(), x.getValue());
});
for (int x = 0; x < strings.size(); x++) {
q.add(new CustomEntry(strings.get(x),calculateStringValue(strings.get(x))));
}
return strings;
}
To use this priority queue
CustomEntry topEntry = q.peek();
System.out.println("key : " + topEntry.getKey());
System.out.println("value : " + topEntry.getValue());
Same logic can be also be applied by using Map.Entry<String, Integer> provided by java for storing key, pair value

not sure if I should search or sort my hashmap

Hi I have a list of people with their ages, I need to find those who are more than 30 years old,
is there any possibility to search in a hashmap ? (please note that I may need to look for those in other age ranges as well so I prefer not to use two different lists for the sake of simplicity of code)
In short: My goal is to find a way to search for elements with specific values in HashMap
Sample list is
element1 40
element2 4
element3 66
element4 5
I want to find those with values more than 40 and those with values more than or equal to 66.
I'd suggest you to use NavigableMap (Implemented as TreeSet).
This implementation is a quite fast - O(log(N)), versus O(N) if you implement index based on lists.
Edit. Example:
class PersonsAgeIndex {
private NavigableMap<Integer, List<Person>> ageToPersons =
new TreeMap<Integer, List<Person>>();
public void addPerson( Person p ) {
List<Person> personsWithSameAge = this.ageToPersons.get( p.age );
if ( personsWithSameAge == null ) {
personsWithSameAge = new LinkedList<Person>();
this.ageToPersons.put( p.age, personsWithSameAge );
}
personsWithSameAge.add( p );
}
public List<Person> personsWithAgeLessThan( int age ) {
List<Person> persons = new LinkedList<Person>();
// persons with less age
for (List<Person> tmp : this.ageToPersons.headMap( age ).values()) {
persons.addAll( tmp );
}
return persons;
}
public List<Person> personsWithAgeInInterval( int minAge, int maxAge ) {
List<Person> persons = new LinkedList<Person>();
// persons with age, which: (minAge <= age <= maxAge)
for (List<Person> tmp : this.ageToPersons.subMap( minAge, true, maxAge, true ).values()) {
persons.addAll( tmp );
}
return persons;
}
}
class Person {
public final int age;
public Person(int age) {
this.age = age;
}
}
Try this:
private List<Person> getPeople(Map<?, Person> peopleMap, int filterAge) {
List<Person> returnList = new ArrayList<Person>(peopleMap.values().size());
for (Person p : peopleMap.values()) {
if (p.getAge() > filterAge)
returnList.add(p);
}
return returnList;
}
HashMapiteration order is 'not predictable' (that's to say that if you sort, and than insert keys, in a determinate order when you later try to iterate the keys the order is not the same).
Use a LinkedHashMap instead.
Good question... unfortunately, a Map needs a very specific key. Your solution above is the only real way to do it.
Alternatively you could maintain two lists, and store those that older than 30 to the 2nd list.
You cannot sort a HashMap, it has no order. If you want an ordered HashMap, use LinkedHashMap.
HashMap<String,String> hmap = new HashMap<String,String>();
SortedSet<String> keys = new TreeSet<String>(hmap.keySet());
This will give you a sorted set which you could make a subset of.
keys.subSet(from,to) e.g keys.subSet(30,100)
and you will have a set with all required elemets.

Categories