I have created a Vector object to store data in Table object as Vector<Table>. Vector<Table> contains components as below.
[Vector<Record> records, String tableName, String keyColumnName, int recordCount, int columnCount]
I need to sort tableName in above Vector to my own order and return Vector<Table> with sorted tableNames for other processes.
How could i do this ?
UPDATED
I have wrote method as below.
private Vector<Table> orderTables(Vector<Table> loadTables) {
ArrayList<String> tableNames = new ArrayList<String>();
for (Table table : loadTables) {
String tblName = table.getTableName();
tableNames.add(tblName);
}
Collections.sort(tableNames, new MyComparable());
return null;
}
But i have no idea about how to write Comparator to this. My own sort order is stored in .properties file. i can read it and get value. but i have no idea about how to compare it.
How could i do it ?
I suggest you use Collections.sort with your own, custom, Comparator.
Just trying to give a pseudocode
TableComparator implements Comparator{
int compare(Table source, Table destination){
//implement your own custom logic of comparison
}
}
Vector<Table> vectorTable = new Vector<Table>();
TableComparator tableComparator = new TableComparator();
Now use this comparator in Collections.sort(vectorTable,tableComparator);
Related
I'm looking to sort a TreeMap of Customer objects by a specific Customer property.
The TreeMap is defined as so:
private TreeMap<Long,Customer> customerMap = new TreeMap<>();
Long is the type of ID for the customers stored.
I wrote a function to create a new TreeMap and pass a Comparator to its constructor which gets map entries, their values, that compares the specific field.
public Customer[] getCustomersByName() {
TreeMap<Long,Customer> sortByName = new TreeMap<> (
new Comparator<Map.Entry<Long,Customer>>() {
#Override public int compare(Map.Entry<Long,Customer> cus1, Map.Entry<Long,Customer> cus2) {
return cus1.getValue().getLastName().compareTo(cus2.getValue().getLastName());
}
}
);
sortByName.putAll(customerMap);
// sortByName to Customer[] and return.
}
This doesn't work and throws: Cannot infer type arguments for TreeMap<>Java(16778094) at Line 2.
Perhaps, the issue is that the Comparator takes <Map.Entry<K,V>> to compare a TreeMap<K,V> and that is the issue.
How would I fix this though to sort by values but keep the customerMap type as is?
I know that TreeMaps are only sorted by keys. Is there a better data structure for this job perhaps so that I could store a bunch of Customer objects and sort them by different Customer properties without the operation being too expensive (not polynomial preferably)?
Set up a second TreeMap, using the customers last name as the key:
TreeMap<String,Customer> sortByName = new TreeMap<>();
TreeMap<Long,Customer> sortByID = new TreeMap<>();
----------------
sortByName.put(customer.getLastName(), customer);
sortByID.put(new Long(customer.getID()), customer);
----------------
return sortByName.values().toArray( new Customer[sortByName.size()] );
'''
This is rather easy with streams:
Customer[] cust =
customerMap.values()
.stream()
.sorted(Comparator.comparing(Customer::getName))
.toArray(Customer[]::new);
You only need to sort the values according to your example, so why bother sorting the TreeMap in reverse, when the only thing you care about is a sorted (by name) Customer[]?
I want to sort my list(taken from the db I can't sort using query), but I don't know for what parameters, the parameters are chosen by the user. The following code sorts by first and last name in desc, but how do I create a dynamic one? I have made many attempts, but I have failed.
myList.sort(Comparator.comparing(DTO::getName)
.thenComparing(DTO::getLastName).reversed());
To create a customized order depending on the user params, I suggest something like :
1- Create an enumeration of the possible sorting orders which will be populated by the parameters in the user query, say that, for example, I have 3 orders BY_ID, BY_NAME, BY_LAST_NAME.
2- Then create a list of this enumeration;
3- After that create a map, where the key is the enumeration above, and the value is a comparator.
4- populate the map.
5-Derive a reduced final comparator from both the list of orders you had in (2), and the map in (3).
6- Sort your list by that final comparator.
Putting all the steps together
The enumeration of the sort orders :
public enum SortOrder {
BY_ID,
BY_NAME,
BY_LAST_NAME;
}
The main test method :
public static void main(String[] args) {
/**dummy objects for test purposes**/
DTO firstDTO = new DTO();
firstDTO.setId(1);
firstDTO.setName("John");
firstDTO.setLastName("Doe");
DTO secondDTO = new DTO();
secondDTO.setId(2);
secondDTO.setName("John");
secondDTO.setLastName("Doe");
DTO thirdDTO = new DTO();
thirdDTO.setId(2); // the id is repeated
thirdDTO.setName("Alice");
thirdDTO.setLastName("Bob");
final List<SortOrder> sortOrders = createSortOrdersFromInputParams(/*the params passed as args*/);
final List<DTO> myList = Arrays.asList(firstDTO, secondDTO, thirdDTO); // your list that is supposed to come from a DB
final Map<SortOrder, Comparator<DTO>> map = new EnumMap<>(SortOrder.class);
final Comparator<DTO> defaultComparator = Comparator.nullsLast(Comparator.comparing(DTO::getId)); // you'all always need a default comparator , say by ID
map.put(SortOrder.BY_ID, defaultComparator);
map.put(SortOrder.BY_NAME, Comparator.nullsLast(Comparator.comparing(DTO::getName)));
map.put(SortOrder.BY_LAST_NAME, Comparator.nullsLast(Comparator.comparing(DTO::getLastName)));
final Comparator<DTO> finalComparator = sortOrders.stream()
.map(map::get)
.filter(Objects::nonNull)
.reduce(Comparator::thenComparing)
.orElse(defaultComparator);
myList.sort(finalComparator);
System.out.println(myList);
}
The method that turns parameters of the user input into sort orders
private static List<SortOrder> createSortOrdersFromInputParams(/*params passed as args*/) {
return Arrays.asList(SortOrder.BY_ID, SortOrder.BY_NAME, SortOrder.BY_LAST_NAME);
}
I hope this will respond to your case.
So i have an interface.
public interface ARecord {
public BigInteger getAutoID();
public String getACompId();
}
and
public class APPPRecord extends AbstratAPRecord implements ARecord{
private BigInteger autoID;
private String ACompId = null;
//setter and getter}
In service,
List<APPPRecord> PFRecord = null;
while(scroll.next()){
APPPRecord item = (APPPRecord) scroll.get(0);
List<ARecord> recs = new ArrayList<ARecord>();
recs.addAll(PFRecord);
My PFRecord list has results that are being duplicated. I have to use hash maps that can check for ACompId contains key. If the key already exists don't pass it to recs.addAll. How can I go about doing this? Any help appreciated
Update: I tried Set and still see duplicate results with HashCode() and equals() in my model class.
for(ARecord records:recs){
uniqueRecs.put(records.getACompId(), records);
Set<String> keys = uniqueRecs.keySet();
for(String key: keys){
log.debug("keys " + key);
}
}
Also tried hashMaps.
HashMap<String, ARecord > uniqueRecs = new HashMap<String, ARecord >();
for(ARecord records:recs){
if(!uniqueRecs.containsKey(records.getACompId())){
uniqueRecs.put(records.getACompId(), records);
for (String key : uniqueRecs.keySet()) {
log.debug("unique record " + key);
}
}
}
Both of them still produce duplicate results. Any ideas?
Replace List<ARecord> recs = new ArrayList<ARecord>();
with Set<ARecord> recs = new HashSet<ARecord>();
and make sure the implementations of the ARecord implements the hashcode/equals methods properly so that your set only contains distinct instances.
Make use of HashMap<K,V> class, This document will provide you with the required API.
And according to your requirement you can make use of .containsKey(Object key) method to check for the existence of the key already.
Update: I suggested this because you asked for HashMap, if duplication is the only issue you have then you can make use of .contains(Object o) method on the List you already have in-place. the interface List<> provides this method which returns a boolean value based on the presence of the value.
I need to store different types of DATA inside one same "array" associated to a key (or an ID) in my android application, and I'm wondering if there's a way to create HashMaps (or equivalent dynamic arrays) that have more than one column of content. Like this for example.
HashMap<Integer, String, LatLng, Marker> myHashMap = new HashMap<Integer, String, LatLng, Marker>();
Thanks in advance for any idea.
private class Row {
public Integer i;
public String s;
public LatLng ll;
public Row(Integer i, String s, LatLng ll) {
this.i = i;
this.s = s;
this.ll = ll;
}
}
List<Row> rows = new ArrayList<Row>();
This is semi pseudo code but I think you get the idea
Adding new Rows to the list can be done with
rows.add(new Row(new Integer(1), "a string", new LatLng(51.448495, 5.470877));
Editing a row can be done with
rowIndex = 3;
Row row = rows.get(rowIndex);
row.i = 2; //give a new value
//etc
Edit: replaced pseude code with real code
map is just a key and value so HashMap makes very little sense
Java does not let you define data structured this way. A collection of type Class A should have hold only instance of Class A or its sub type.
EDIT: From the data you have provided seems like you want to process each row from a database table. Most appropriate data structure for it is to have a class with fields that correspond to a database table.
When you fetch a row from the a result set just create an instance of this class.
Class mysqlTuple
{
public Integer id;
public String message;
public LatLng latitude;
public Marker longitude;
}
mysqlTupe [] mysqlTable = new mysqlTupe [];
It depends a lot on what you are trying to achieve
One option is to keep 3 different maps:
Map<String, Integer>
Map<String,Marker>
Map<String,LatLng>
Another option is to make a:
Map<String,Object>
However you will have to 'instanceof' to check the real type, which is not a best practice.
Here is my problem
I have a list of 'System Exceptions' and I need to select distinct values from the list based on two keys. So I am creating a compositeKey and storing it in a list as a string 'key1:key2' Is there a better approach to this ?
Collection uniqueExceptions = CollectionUtils.select(allSubareaExceptions, new Predicate(){
private List<String> ids = new ArrayList<String>();
public boolean evaluate(Object obj) {
....domain.Exception ex = (....domain.Exception)obj;
String compositeKey = ex.getProcedure().getSubarea().getId() +":"+ex.getProcedure().getId();
if(ids.contains(compositeKey) == false){
ids.add(compositeKey);
return true;
}
return false;
}
});
There are several options. You could create a list:
List<String> compositKey = Arrays.asList(getSubareaId(), getProcedureId());
You could use an AbstractMap.SimpleEntry (1.6 or later only):
SimpleEntry<String, String> compositKey = new SimpleEntry(getSubareaId(), getProcedureId());
You could create your own pair implementation, or even a composite key class.
The major danger of using concatenation is if : is a legal character in the id strings, then you could get false duplicates.
you can override the equals() in the exception class to check on the "compositeKey". then create a Set off the list (set.addAll()) and there you go. u have a unique set of exceptions