Sorting based on all heighest number - java

I want to get the person having highest values from all the tables. Below is the example which i retrieve from db
Id play(count) listen(count) display(count) comment(count)
a 3 1 4 2
b 2 5 3 7
c 6 3 0 1
d 0 0 5 4
e 6 4 8 9
f 4 2 5 7
in this all counts related to same id but coming from different tables.Here I want e(6,4,8,9) as sorting output. How can i do this sorting?

Try something like this:
Map<String, List<Integer>> map = new LinkedHashMap<>();
// Assuming that you are working with query output resultset
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
List<Integer> li = new ArrayList<>();
li.add(rs.getInt("PLAY"));
li.add(rs.getInt("LISTEN"));
li.add(rs.getInt("DISPLAY"));
li.add(rs.getInt("COMMENT"));
map.put(rs.getString("ID"), li);
}
} catch (SQLException e ) {
/* SQLException handler */
} finally {
if (stmt != null) { stmt.close(); }
}
map = sortByValues(map);
for (Map.Entry<String, List<Integer>> entry: map.entrySet()) {
System.out.println(entry.getKey() + "," + entry.getValue());
}
}
public static Map<String, List<Integer>> sortByValues(Map<String, List<Integer>> map) {
List<Map.Entry<String, List<Integer>>> list =
new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, List<Integer>>>() {
public int compare(Map.Entry<String, List<Integer>> m1, Map.Entry<String, List<Integer>> m2) {
int sum1 = 0;
for(Integer d : m1.getValue())
sum1 += d;
int sum2 = 0;
for(Integer d : m2.getValue())
sum2 += d;
return (new Integer(sum2)).compareTo(new Integer(sum1));
}
}) ;
Map<String, List<Integer>> result = new LinkedHashMap<>();
for (Map.Entry<String, List<Integer>> entry: list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Note: I have a separate method sortByValues() to do the comparison. This makes code neat to read and reusable rather than implementing an anonymous block after try-catch.
What's happening here?
Our aim is to sort IDs by different values fetched from Database. I feel Map data structure to be the apt one here. Example Map which is represented in a generic way as Map<String, List<Integers>>.
Map<String, List<Integer>> map = new LinkedHashMap<>();
Creates the linked hash map to store the pair
List<Integer> li = new ArrayList<>();
Creates an Arraylist object inside while loop to store each value fetched from database. It's scope dies within this loop.
map.put(id, li);
Adds each users id and values in the format Map<String, List<Integer>>
map = sortByValues(map);
Accesses the static sortByValues() to fetch the sorted map based on values it has.
sortByValues(Map<String, List<Integer>> map)
Overrides the Comparator's compare() anonymously and performs sorting based upon values. It sums up each ID's value and does the comparison.
Mock Execution:
Map<String, List<Integer>> map = new LinkedHashMap<>();
// Map<String, List<Integer>> map = new HashMap<>();
List<Integer> li = new ArrayList<>();
li.add(1);
li.add(2);
li.add(3);
// MathUtils.sum()
map.put("a", li);
// map.put("a", 5);
List<Integer> li2 = new ArrayList<>();
li2.add(3);
li2.add(-1);
li2.add(1);
map.put("b", li2);
List<Integer> li3 = new ArrayList<>();
li3.add(10);
li3.add(-1);
li3.add(9);
map.put("c", li3);
map = sortByValues(map);
for (Map.Entry<String, List<Integer>> entry: map.entrySet()) {
System.out.println(entry.getKey() + "," + entry.getValue());
}
Result:
c,[10, -1, 9]
a,[1, 2, 3]
b,[3, -1, 1]

Related

Convert keys to Values

I'm trying to convert the keys of a Map to Values of another Map, but finally only one key was return as Value. What was the problem?
when the program excuted I got different Result
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class KeystoValues {
public static void KtoV(Map<Double, Integer> Key) {
Map<Double, Integer> List = new HashMap<Double, Integer>();
Map<Integer, Double> KeystoV = new HashMap<Integer, Double>();
System.out.println("List Map\n");
List.putAll(Key);
for(Map.Entry<Double, Integer> val : List.entrySet()) {
System.out.println(val.getKey() + "," + val.getValue());
}
for(int h = 1; h<=List.size(); h++)
for(Map.Entry<Double, Integer> convert : List.entrySet()) {
Double j = convert.getKey();
KeystoV.put(h, j);
}
System.out.println("\nSet of keys in List Map now converted to set "
+ "of Values and stored to KeystoV Map\n\nKeystoV Map\n");
for(Map.Entry<Integer, Double> converted : KeystoV.entrySet()) {
System.out.println(converted.getKey() + "," + converted.getValue());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Integer> Value = new ArrayList<Integer>();
Map<Double, Integer> Key = new HashMap<Double, Integer>();
Key.put(45.0,1);
Key.put(40.0,2);
Key.put(23.0,2);
Key.put(25.0,3);
Key.put(0.0,1);
KtoV(Key);
}
}
List Map
0.0,1
25.0,3
40.0,2
45.0,1
23.0,2
Set of keys in List Map now converted to set of Values and stored to KeystoV Map
KeystoV Map
1,23.0
2,23.0
3,23.0
4,23.0
5,23.0
The problem with your code is this nested for loop:
for(int h = 1; h<=List.size(); h++)
for(Map.Entry<Double, Integer> convert : List.entrySet()) {
Double j = convert.getKey();
KeystoV.put(h, j);
}
If you debug it, then you'll see that you are always putting the last iterated value of List.entrySet() as the value of all keys.
Try changing it to:
int index = 1;
for (Map.Entry<Double, Integer> convert : List.entrySet()) {
KeystoV.put(index, convert.getKey());
index++;
}
You have to use a list for the second map values because some of your values could appear twice and that would result in duplicate keys which maps can't support.
Collectors.groupingBy creates a map using a supplied key
Collectors.mapping gets the key as the value for entry into the value which is a list of doubles.
Try it like this.
Map<Double, Integer> map = Map.of(2.0, 1, 3.0, 1, 8.0, 5, 9.0, 7, 4.0, 7);
Map<Integer, List<Double>> keystoV = map.entrySet().stream().collect(Collectors.groupingBy(Entry::getValue,
Collectors.mapping(Entry::getKey, Collectors.toList())));
map.entrySet().forEach(System.out::println);
System.out.println();
keystoV.entrySet().forEach(System.out::println);
prints
9.0=7
8.0=5
2.0=1
3.0=1
4.0=7
1=[2.0, 3.0]
5=[8.0]
7=[9.0, 4.0]
Here is a loop version using the Map.computeIfAbsent method.
if key is absent, create a list for that key.
it also returns the list so the new value (old key) many be added to the list.
keystoV.entrySet().forEach(System.out::println);
Map<Integer, List<Double>> result = new HashMap<>();
for(Entry<Double, Integer> e : map.entrySet()) {
result.computeIfAbsent(e.getValue(), v->new ArrayList<>()).add(e.getKey());
}
result.entrySet().forEach(System.out::println);
prints
1=[2.0, 3.0]
5=[8.0]
7=[9.0, 4.0]

Leaderboard displaying entire list instead of pagination

I have a list of users (stored in a properties file) that have a level. I sort the users by their level and then send the sorted list back to the guild. I paginate the list, but its still showing all of the users instead of just 10 per page.
Map<String, Integer> unsortedMap = new HashMap<String, Integer>();
for (String key : prop.stringPropertyNames()) {
String value = prop.getProperty(key);
unsortedMap.put(key, Integer.valueOf(value));
}
Map<String, Integer> sortedMap = sortByValue(unsortedMap);
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("aaaaaaaaaaaa");
ArrayList<Page> pages = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
if (key.contains(".level")) {
User users = ctx.getJDA().retrieveUserById(key.replace(".level", ""), true).complete();
eb.addField(users.getName(), String.valueOf(value), false);
}
}
for (int i = 0; i < sortedMap.size(); i++){
pages.add(new InteractPage(eb.build()));
}
channel.sendMessageEmbeds((MessageEmbed) pages.get(0).getContent()).queue(success -> {
Pages.paginate(success, pages, true);
});
}
private static Map<String, Integer> sortByValue(Map<String, Integer> unsortedMap) {
List<Map.Entry<String, Integer>> list = new LinkedList<Map.Entry<String, Integer>>(unsortedMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return (o2.getValue().compareTo(o1.getValue()));
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Map.Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
Partition the for loop into smaller parts using the for loop. Initialize the int outside of the loop and then increment the int for every entry and then divide the int by how many items you want displayed on the list. Ex:
int i = 0;
for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
i++;
if (i % 6 == 0) {
//add page here

Using Hashmaps to compare keys and values and add together values based on similar keys

So i was wondering how and if it was possible using Hashmaps, one containing only strings and the other containing a similar string key but a float value, to compare them and then from that comparison print out the amount of similar values in the first hashmap, and then the float from the second hashmap added together when their keys/values line up. Example below that should clarify what i mean and to do this dynamically.
CODE
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, Float> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", (float) 19.95);
h2map.put("order2", (float) 19.95);
h2map.put("order3", (float) 39.9);
Set <String> singles = new HashSet<>(h2map.values());
if(h2map.keySet().equals(hmap.keySet())) {
// below prints out the states and amount of the states but how can i get the float values from hmap to be added together for the similar states and printed with their respective state?
for(String element : singles) {
System.out.println(element + ": " + Collections.frequency(hmap.values(), element));
}
}
Current Output
pending: 2
cancelled: 1
Desired Output
pending: 2 $59.85
cancelled 1 $19.95
Is this what you want?
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, Float> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", 19.95f);
h2map.put("order2", 19.95f);
h2map.put("order3", 39.9f);
Map<String, DoubleSummaryStatistics> grouping = hmap
.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.summarizingDouble(e -> h2map.get(e.getKey()))));
grouping.forEach((key, value) -> System.out.println(key + ": " + value.getCount() + " " + value.getSum()));
}
Note that there is no summarizing statistics collector for BigDecimal and this code works only with Float or Double. But for money calculations better use BigDecimal. It's possible to implement the custom collector if needed )
I have replaced the use of Float with BigDecimal for better accuracy. Also I used two maps, one for holding the summed value and the other for count:
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, BigDecimal> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", new BigDecimal("19.95"));
h2map.put("order2", new BigDecimal("19.95"));
h2map.put("order3", new BigDecimal("39.9"));
//Map for holding sum
HashMap<String, BigDecimal> sum = new HashMap<>();
for(String key : h2map.keySet()){
if(hmap.get(key) != null){
String value = hmap.get(key);
if(sum.get(value) == null){
sum.put(value, h2map.get(key));
}else{
sum.put(value, (sum.get(value).add(h2map.get(key))));
}
}
}
//Map for holding count
HashMap<String, BigDecimal> countMap = new HashMap<>();
for(Iterator<Map.Entry<String, BigDecimal>> itr = sum.entrySet().iterator(); itr.hasNext(); ){
Map.Entry<String, BigDecimal> entry = itr.next();
String key = entry.getKey();
int count = Collections.frequency(hmap.values(), key);
countMap.put((key + count), sum.get(key));
itr.remove();
}
//For GC
sum = null;
countMap.forEach((k, v) -> System.out.println(k + " " + v));
}

Storing and Retrieving ArrayList values from hashmap

I have a hashmap of the following type
HashMap<String,ArrayList<Integer>> map=new HashMap<String,ArrayList<Integer>>();
The values stored are like this :
mango | 0,4,8,9,12
apple | 2,3
grapes| 1,7
peach | 5,6,11
I want to store as well as fetch those Integers using Iterator or any other way with minimum lines of code.How can I do it?
EDIT 1
The numbers are added at random (not together) as key is matched to the appropriate line.
EDIT 2
How can I point to the arraylist while adding ?
I am getting error while adding a new number 18 in the line map.put(string,number);
Our variable:
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
To store:
map.put("mango", new ArrayList<Integer>(Arrays.asList(0, 4, 8, 9, 12)));
To add numbers one and one, you can do something like this:
String key = "mango";
int number = 42;
if (map.get(key) == null) {
map.put(key, new ArrayList<Integer>());
}
map.get(key).add(number);
In Java 8 you can use putIfAbsent to add the list if it did not exist already:
map.putIfAbsent(key, new ArrayList<Integer>());
map.get(key).add(number);
Use the map.entrySet() method to iterate on:
for (Entry<String, List<Integer>> ee : map.entrySet()) {
String key = ee.getKey();
List<Integer> values = ee.getValue();
// TODO: Do something.
}
The modern way (as of 2020) to add entries to a multimap (a map of lists) in Java is:
map.computeIfAbsent("apple", k -> new ArrayList<>()).add(2);
map.computeIfAbsent("apple", k -> new ArrayList<>()).add(3);
According to Map.computeIfAbsent docs:
If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
Returns:
the current (existing or computed) value associated with the specified key, or null if the computed value is null
The most idiomatic way to iterate a map of lists is using Map.forEach and Iterable.forEach:
map.forEach((k, l) -> l.forEach(v -> /* use k and v here */));
Or, as shown in other answers, a traditional for loop:
for (Map.Entry<String, List<Integer>> e : map.entrySet()) {
String k = e.getKey();
for (Integer v : e.getValue()) {
/* use k and v here */
}
}
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
if(pairs.getKey().equals("mango"))
{
map.put(pairs.getKey(), pairs.getValue().add(18));
}
else if(!map.containsKey("mango"))
{
List<Integer> ints = new ArrayList<Integer>();
ints.add(18);
map.put("mango",ints);
}
it.remove(); // avoids a ConcurrentModificationException
}
EDIT:
So inside the while try this:
map.put(pairs.getKey(), pairs.getValue().add(number))
You are getting the error because you are trying to put an integer to the values, whereas it is expected an ArrayList.
EDIT 2:
Then put the following inside your while loop:
if(pairs.getKey().equals("mango"))
{
map.put(pairs.getKey(), pairs.getValue().add(18));
}
else if(!map.containsKey("mango"))
{
List<Integer> ints = new ArrayList<Integer>();
ints.add(18);
map.put("mango",ints);
}
EDIT 3:
By reading your requirements, I come to think you may not need a loop. You may want to only check if the map contains the key mango, and if it does add 18, else create a new entry in the map with key mango and value 18.
So all you may need is the following, without the loop:
if(map.containsKey("mango"))
{
map.put("mango", map.get("mango).add(18));
}
else
{
List<Integer> ints = new ArrayList<Integer>();
ints.add(18);
map.put("mango", ints);
}
You can use like this(Though the random number generator logic is not upto the mark)
public class WorkSheet {
HashMap<String,ArrayList<Integer>> map = new HashMap<String,ArrayList<Integer>>();
public static void main(String args[]) {
WorkSheet test = new WorkSheet();
test.inputData("mango", 5);
test.inputData("apple", 2);
test.inputData("grapes", 2);
test.inputData("peach", 3);
test.displayData();
}
public void displayData(){
for (Entry<String, ArrayList<Integer>> entry : map.entrySet()) {
System.out.print(entry.getKey()+" | ");
for(int fruitNo : entry.getValue()){
System.out.print(fruitNo+" ");
}
System.out.println();
}
}
public void inputData(String name ,int number) {
Random rndData = new Random();
ArrayList<Integer> fruit = new ArrayList<Integer>();
for(int i=0 ; i<number ; i++){
fruit.add(rndData.nextInt(10));
}
map.put(name, fruit);
}
}
OUTPUT
grapes | 7 5
apple | 9 5
peach | 5 5 8
mango | 4 7 1 5 5
You could try using MultiMap instead of HashMap
Initialising it will require fewer lines of codes. Adding and retrieving the values will also make it shorter.
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
would become:
Multimap<String, Integer> multiMap = ArrayListMultimap.create();
You can check this link: http://java.dzone.com/articles/hashmap-%E2%80%93-single-key-and
Method1 : Use putIfAbsent
Map<String, List<Integer>> map = new HashMap();
map.putIfAbsent("mango",new ArrayList<>());
map.get("mango").add(5);
Method 2: Check key present in Map
Map<String, List<Integer>> map = new HashMap();
if(! map.containsKey("mango"){
map.put("mango",new ArrayList<>());
}
List<Integer> list = map.get("mango");
list.add(3);
Method 3: Use getOrDefault
Map<String, List<Integer>> map = new HashMap();
List<Integer> list = map.getOrDefault("mango",new ArrayList<>());
list.add(4)
for (Map.Entry<String, ArrayList<Integer>> entry : map.entrySet()) {
System.out.println( entry.getKey());
System.out.println( entry.getValue());//Returns the list of values
}
static HashMap<Integer, ArrayList<Integer>> has(int arr[], int target) {
HashMap<Integer, ArrayList<Integer>> hm = new HashMap<Integer, ArrayList<Integer>>();
for (int i = 0; i < arr.length; i++) {
if (!hm.containsKey(arr[i])) {
ArrayList<Integer> res = new ArrayList<Integer>();
res.add(i + 1);
hm.put(arr[i], res);
} else {
hm.get(arr[i]).add(i);
}
}
return hm;
}
Fetch all at once =
List<Integer> list = null;
if(map!= null)
{
list = new ArrayList<Integer>(map.values());
}
For Storing =
if(map!= null)
{
list = map.get(keyString);
if(list == null)
{
list = new ArrayList<Integer>();
}
list.add(value);
map.put(keyString,list);
}

Sorting by values in HashMap class using Java

I'm trying to get results HashMap sorted by value.
This is HashMap's keys and values:
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
I try to get results like this:
1 = can
2 = selin
4 = burak
5 = ertu
Here is my code:
import java.util.*;
public class mapTers {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
Integer dizi[] = new Integer[map.size()];
Set anahtarlar = map.keySet();
Iterator t = anahtarlar.iterator();
int a = 0;
while (t.hasNext()) {
dizi[a] = map.get(t.next());
a++;
}
Arrays.sort(dizi);
for (int i = 0; i < map.size(); i++) {
while (t.hasNext()) {
if (dizi[i].equals(map.get(t.next()))) {
System.out.println(dizi[i] + " = " + t.next());
}
}
}
}
}
You can sort the entries as follows (but note this won't sort the map itself, and also HashMap cannot be sorted) -
List<Map.Entry<String, Integer>> entryList = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
Every time that you call t.next(), the iterator's pointer is moved forward. Eventually, the iterator reaches the end. You need to reset the iterator. Also, calling t.next() twice moves the pointer twice.
Here's my solution:
import java.util.*;
public class mapTers
{
public static void main(String[] args)
{
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
Integer dizi[] = new Integer[map.size()];
Set anahtarlar = map.keySet();
Iterator t = anahtarlar.iterator();
int a = 0;
while (t.hasNext())
{
dizi[a] = map.get(t.next());
a++;
}
Arrays.sort(dizi);
for (int i = 0; i < map.size(); i++)
{
t = anahtarlar.iterator();
while (t.hasNext())
{
String temp = (String)t.next();
if (dizi[i].equals(map.get(temp)))
{
System.out.println(dizi[i] + " = " + temp);
}
}
}
}
}
You cannot do that from a Map. At least not directly.
Retrieve the keys/entries, get all the map data in a more suitable structure (hint: a class that encapsulates both attributes and is is stored in a sortable (hint2: SortedSet, List)) and sort.
Do not forget to extend Comparable (and implement compareTo) or, otherwise, create a Comparator.
This is one of the solutions take from: https://stackoverflow.com/a/13913206/1256583
Just pass in the unsorted map, and you'll get the sorted one.
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap, final boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getValue().compareTo(o2.getValue());
}
else {
return o2.getValue().compareTo(o1.getValue());
}
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
To print, do a simple iteration over the entry set:
public static void printMap(Map<String, Integer> map) {
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
}
}
You probably have the wrong data structure for this problem. Either:
Reverse the map so the integers are the keys and the words the values and make the map a SortedMap, or
Use a bidirectional map as provided by libraries like Google Guava.
Reversed Map
private final SortedMap<Integer, String> TRANSLATIONS;
static {
SortedMap<Integer, String> map = new TreeMap<>();
map.put(1, "can");
// ...
TRANSLATIONS = Collections.unmodifiableSortedMap(map);
}
Guava BiMap
private final BiMap TRANSLATIONS =
new ImmutableBiMap.Builder<String, Integer>()
.put("ertu", 5);
.put("burak", 4);
.put("selin", 2);
.put("can", 1);
.build();
Then, iterate over a sorted version of the key set or value set as needed. For example,
TRANSLATIONS.inverse.get(4); // "burak"
I'm just curious. What language are your strings in?

Categories

Resources