How to increase integer field in List of objects - java

well, I have List<HighscoreEntry> In which your class is this:
public class HighscoreEntry {
private List<String> users;
private int score;
HighscoreEntry(List<String> users, int score) {
this.users = users;
this.score = score;
}
public List<String> getUsers() {
return users;
}
public void setUsers(List<String> users) {
this.users = users;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
Well, what happens, is because in the other class I have this:
public class ScoreboardItemData {
private final static HighscoreComparator comparator = new HighscoreComparator();
private final List<HighscoreEntry> entries;
private final Map<String, Integer> points;
private int scoreType;
private int clearType;
public ScoreboardItemData(int scoreType, int clearType, List<HighscoreEntry> entries, Map<String, Integer> points) {
this.scoreType = scoreType;
this.clearType = clearType;
this.entries = entries;
this.points = points;
}
public List<HighscoreEntry> getEntries() {
return this.entries;
}
public Map<String, Integer> getPoints() {
return this.points;
}
public void addEntry(List<String> users, int score) {
synchronized (this.entries) {
this.entries.add(new HighscoreEntry(users, score));
this.entries.sort(comparator);
}
} }
Well, I already can add new entries, but I want to change ONLY THE SCORE and increase it, to existing data.
And I tried some things, but without success:
Example 1:
synchronized (this.entries) {
for (int i = 0;i < this.entries.size(); i++) {
if (this.entries.get(i).getUsers() == users) {
this.entries.get(i).increaseScore(score);
this.entries.sort(comparator);
} else {
this.entries.add(new HighscoreEntry(users, score));
this.entries.sort(comparator);
}
}
}
This example update the score, but with the loop, he will add more entries and update others, so will always do this loop.
Example 2:
HighscoreEntry entry = (HighscoreEntry) this.entries.stream().filter((x) -> {
return x.getUsers().equals(users);
});
if (entry.getUsers() != null) {
entry.increaseScore(score);
} else {
entry.setUsers(users);
entry.setScore(score);
}
And this one, return this error:
java.lang.ClassCastException: java.util.stream.ReferencePipeline$2 cannot be cast to com.heraproject.wired.data.ScoreboardItemData$HighscoreEntry
at com.heraproject.wired.data.ScoreboardItemData.addEntry(ScoreboardItemData.java:45)

You need to find the right item in the list based on the identifier and looking at HighscoreEntry that identifier is users. This code will update the score for a HighscoreEntry in the list entries if one exists
public void addScore(List<String> users, int score) {
HighscoreEntry entry = entries.filter( e -> (e.getUsers().equals(users))).findFirst().orElse(null);
if (entry != null) {
entry.setScore(score);
}
}

If I understand correctly, all you need is something like this
// int index, someInt;
this.entries.get(index).setScore(someInt);
However, looking at your model, I would think "high score" would be calculated by iterating over a list of potential User objects, each having their own unique scores. Then you set the score on the user, not the entity holding a list of users.

Well,
Use this method
public void updateEntry(List<String> users, int index) {
synchronized (this.entries) {
HighscoreEntry highScoreEntry = this.entries.get(index);
highscoreEntry.setScore(//Update score);
entries.add(index, highscoreEntry);
}
}

Related

ArrayList occurance of object type

I have a class of orders and I want to see how many times a unique customerNumber will get mapped to a status reading "On Hold"
public class Orders {
private String status = null;
private int customerNumber = 0;
public Orders(String status, int customerNumber) {
super();
this.status = status;
this.customerNumber = customerNumber;
}
}
public int NumberOfOrdersOnHold(List<Orders> orders) {
int sum = 0;
for (Orders o : orders) {
if(o.getStatus().contentEquals("On Hold"));
}
}
I was thinking a counter method would work but it wouldnt. how will i achieve this method.I need numbers of orders in hold for each customerNumber not the total number.
Do it as follows:
import java.util.List;
enum OrderStatus {
ONHOLD("On Hold"), APPROVED("Approved"), DELIVERED("Delivered");
private final String statusCode;
private OrderStatus(String statusCode) {
this.statusCode = statusCode;
}
}
class Order {
private OrderStatus status = null;
private int customerNumber = 0;
public Order(OrderStatus status, int customerNumber) {
this.status = status;
this.customerNumber = customerNumber;
}
public OrderStatus getStatus() {
return status;
}
public void setStatus(OrderStatus status) {
this.status = status;
}
public int getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(int customerNumber) {
this.customerNumber = customerNumber;
}
#Override
public String toString() {
return "Order [status=" + status + ", customerNumber=" + customerNumber + "]";
}
}
public class Main {
public static void main(String[] args) {
List<Order> orders = List.of(new Order(OrderStatus.ONHOLD, 1234), new Order(OrderStatus.APPROVED, 1234),
new Order(OrderStatus.ONHOLD, 2345), new Order(OrderStatus.APPROVED, 1234),
new Order(OrderStatus.ONHOLD, 1234), new Order(OrderStatus.ONHOLD, 2345));
System.out.println("Customer#1234 has " + numberOfOrdersOnHold(orders, 1234) + " order(s) on hold");
}
static int numberOfOrdersOnHold(List<Order> orders, int customerNumber) {
int count = 0;
for (Order order : orders) {
if (order.getCustomerNumber() == customerNumber && order.getStatus() == OrderStatus.ONHOLD) {
count++;
}
}
return count;
}
}
Output:
Customer#1234 has 2 order(s) on hold
Notes:
Use enum for status values as it makes easy for you to write and maintain the code. Check this to learn more about Java enum.
Follow Java naming conventions e.g. NumberOfOrdersOnHold should be named as numberOfOrdersOnHold.
The function, numberOfOrdersOnHold also requires the customer number whose order status has to be found.
You can use a Map! Try something like this:
public Map<Integer, Integer> numberOfOrdersOnHold(List<Orders> orders) {
final Map<Integer, Integer> map = new HashMap<>();
for (Orders o : orders) {
int currentNumber = o.getCustomerNumber();
// if map doesn't contain the key to the corresponding customer, were gonna add it
if (!map.containsKey(currentNumber)) {
map.put(currentNumber, 0);
}
// if the status is "On hold", increment the counter to the current customer
if ("On hold".equals(o.getStatus())) {
map.put(currentNumber, map.get(currentNumber) + 1);
}
}
return map;
}

ArrayLists and returning null

I'm trying finish my method 'priority' which should return the priority of the Task. and make it return null if the specified name does not exist (as shown in the main). I've tried iterating through the ArrayList, but i don't think this is the way to do it. Is there anyone who can help me out?
class Task
{
public static final ArrayList<Task> ALL_TASKS = new ArrayList<>();
private String name;
private Integer priority;
public Task(String name, Integer priority)
{
this.name = name;
this.priority = priority;
ALL_TASKS.add(this);
}
#Override public String toString()
{
return "name: " + this.name + "\tpriority: " + this.priority;
}
}
class Main
{
public static void main(String[] arguments)
{
new Task("Clean", 5);
new Task("Dishwash", 4);
new Task("Study", 1);
System.out.println(Task.priority("Dishwash"));
System.out.println(Task.priority("Vacuumclean"));
}
}
Try this:
public static Integer priority(String name) {
for(Task task : ALL_TASKS) {
if(task.name.equals(name)) {
return task.priority;
}
}
return null;
}
Or using Stream-API:
public static Integer priority(String name) {
return ALL_TASKS.stream()
.filter(task -> task.name.equals(name))
.map(task -> task.priority)
.findFirst()
.orElse(null);
}
public static Integer priority(String name) {
for(int i = 0; i < ALL_TASKS.size(); i++){
if(ALL_TASKS.get(i).getName().equals(name))
return ALL_TASKS.get(i).getPriority();
else
return null; // but if using Java 8 Option<Task> would be better
}
}
This is the example which I would use. It is not tested but it give you idea what create and the way of thinking.
Also in my solution I assume you also create getName() and getPriority() methods for your Task
The Java Stream API provides a more convenient and efficient approach to iterating and processing elements of a collection.
class Task
{
public static final ArrayList<Task> ALL_TASKS = new ArrayList<>();
public static Integer priority(String name)
{
List<Task> result = ALL_TASKS.stream().filter(task->
(task.name.equals(name))).collect(Collectors.toList());
if(result.isEmpty())
{
return null;
}
else
{
return result.get(0).priority;
}
}
private String name;
private Integer priority;
public Task(String name, Integer priority)
{
ALL_TASKS.add(this);
this.name = name;
this.priority = priority;
}
public String toString()
{
return "name: " + this.name + "\tpriority: " + this.priority;
}
}
class Main
{
public static void main(String[] arguments)
{
new Task("Clean", 5);
new Task("Dishwash", 4);
new Task("Study", 1);
System.out.println(Task.priority("Dishwash"));
System.out.println(Task.priority("Vacuumclean"));
}
}
An option would be storing your List as a Map instead, using the tasks name as the key
HashMap<String, Task> ALL_TASKS = new HashMap<>();
Task task = ALL_TASKS.get(codeIsIn);
if(task!=null)
{
Integer priority = task.priority;
}
If a Task consists only of name and priority, it gets even simpler
HashMap<String, Integer> ALL_TASKS = new HashMap<>();
Integer priority = ALL_TASKS.get(codeIsIn);
//null if nonexistent

Java Comparator will calculate score 1 time or several times

I need to sort a list with my custom comparator: Collections.sort(availableItems, new TextClassifyCnnComparator(citem, false))
class TextClassifyCnnComparator implements Comparator<Item> {
private Item citem;
private boolean isAsc;
public TextClassifyCnnComparator(Item citem) {
this(citem, true);
}
public TextClassifyCnnComparator(Item citem, boolean isAsc) {
this.citem = citem;
this.isAsc = isAsc;
}
private Double calcSimilarScore(Item item) {
return item.getEncodedFromCNN().dotProduct(citem.getEncodedFromCNN());
}
#Override
public int compare(Item o1, Item o2) {
if (isAsc) {
return calcSimilarScore(o1).compareTo(calcSimilarScore(o2));
}
return calcSimilarScore(o2).compareTo(calcSimilarScore(o1));
}
}
Will Java map and call calcSimilarScore 1 time for each item or it would be called several times (1 for each tuple 2 item)?
If it call several times, how can I optimize this task?
========= Update 1: ===============
I have refract my comparator in this:
class TextClassifyCnnComparator implements Comparator<Integer> {
private boolean isAsc;
private List<Double> list;
public TextClassifyCnnComparator(Item citem, List<Item> list) {
this(citem, list, true);
}
public TextClassifyCnnComparator(Item citem, List<Item> list, boolean isAsc) {
this.list = list.parallelStream().map(item -> calcSimilarScore(item, citem)).collect(Collectors.toList());
this.isAsc = isAsc;
}
private Double calcSimilarScore(Item item1, Item item2) {
return item1.getEncodedFromCNN().dotProduct(item2.getEncodedFromCNN());
}
public List<Integer> createIndexes() {
List<Integer> indexes = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
indexes.add(i); // Autoboxing
}
return indexes;
}
#Override
public int compare(Integer index1, Integer index2) {
// Autounbox from Integer to int to use as array indexes
if (isAsc)
return list.get(index1).compareTo(list.get(index2));
return list.get(index2).compareTo(list.get(index1));
}
}
...
TextClassifyCnnComparator comparator = new TextClassifyCnnComparator(citem, availableItems);
List<Integer> indexes = comparator.createIndexes();
Collections.sort(indexes, comparator);
return indexes.parallelStream().map(index -> availableItems.get(index)).collect(Collectors.toList());
I think it still can be optimized more.
There are the following optimizations:
One should use double (the "primitive" data type) instead of Double (the Object wrapper class holding a double), wherever feasible.
Of the compared citem a part can be precalculated in the constructor. (citem might even not be needed anymore as field.)
A value may be compared several times, so a cache is possible, a Map from Item to its double value.
So
class TextClassifyCnnComparator implements Comparator<Item> {
private final Item citem;
private final boolean isAsc;
private final ECNN encodedFromCNN;
private Map<Item, Double> scores = new HashMap<>();
public TextClassifyCnnComparator(Item citem) {
this(citem, true);
}
public TextClassifyCnnComparator(Item citem, boolean isAsc) {
this.citem = citem;
this.isAsc = isAsc;
encodedFromCNN = citem.getEncodedFromCNN();
}
private double calcSimilarScore(Item item) {
Double cached = scores.get(item);
if (cached != null) {
return cached;
}
double score = item.getEncodedFromCNN().dotProduct(encodedFromCNN);
scores.put(Item, score);
return score;
}
#Override
public int compare(Item o1, Item o2) {
if (isAsc) {
return calcSimilarScore(o1).compareTo(calcSimilarScore(o2));
}
return calcSimilarScore(o2).compareTo(calcSimilarScore(o1));
}
}
Or stylish in java 8:
private double calcSimilarScore(Item item) {
return scores.computeIfAbsent(item,
it -> it.getEncodedFromCNN().dotProduct(encodedFromCNN));
}

how to generate unique questions by overriding hashcode and equals method

My program reads question details from a QuestionBank.sql file. Everything is right but instead of getting 12 questions the output contains 10 questions.
The Output is:
GK Simple
GK Simple
GK Medium
GK Complex
Science Complex
History Medium
History Medium
History Simple
History Simple
Geography Medium
**DataManagerImpl.java**
#Override
public Set<Question> generateQuestionPaper(List<Question> list,
List<Criteria> template) {
// TODO Auto-generated method stub
Set<Question> questionSet = new HashSet<Question>();
int count;
int index = 0;
for(Criteria c: template){
count = 0;
while(c.getNoOfQuestion() > count){
index = (int)(Math.random()*list.size());
//System.out.println(index);
Question q = list.get(index);
if(c.getCategory().equals(q.getCategory()) && c.getComplexity().equals(q.getComplexity()) ){
if(!questionSet.contains(q)){
count++;
questionSet.add(q);
System.out.println(q.getCategory()+" "+q.getComplexity());
}
}
}
}
return questionSet;
}
Criteria.java
public class Criteria {
private Category category;
private Complexity complexity;
private int noOfQuestion;
public Criteria() {
}
public Criteria(Category category, Complexity complexity,int noOfQuestion) {
super();
this.noOfQuestion = noOfQuestion;
this.category = category;
this.complexity = complexity;
}
public int getNoOfQuestion() {
return noOfQuestion;
}
public void setNoOfQuestion(int noOfQuestion) {
this.noOfQuestion = noOfQuestion;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Complexity getComplexity() {
return complexity;
}
public void setComplexity(Complexity complexity) {
this.complexity = complexity;
}
}
List template contains: (Passed as parameter to generateQuestionpaper()
Please help me!!
Problem is with the definition of Math.random() method.
Try after modifying your code as below -
Random random = new Random();
for(Criteria c: template){
count = 0;
while(c.getNoOfQuestion() > count){
index = random.nextInt(list.size());
As, list index is also zero based this should work fine.

sorting using comparable java

I'm trying to sort an array of records. But I get "not a Record" error. The method getCt() is in a different class, the program compiles and the array is of the record type. I really don't know what is wrong with this code.
HashTable:
public class HashTable {
private Record [] array;
private int size;
private int indexSize=0;
private boolean updated,found;
public HashTable(int m){
array= new Record[m];
size=0;
}
public void getCt() {
Arrays.sort(array);
// return array[0];
}
Record class:
import java.lang.Comparable;
import java.util.*;
public class Record implements Comparable {
private Integer count;
private DNSkey key;
public Record(DNSkey key) {
this.key = key;
count = 1;
}
public void update() {
count++;
}
public DNSkey getKey() {
return key;
}
public Integer getCount() {
return count;
}
public int compareTo(Object obj) {
if (!(obj instanceof Record)) {
throw new ClassCastException("Not a Record");
}
Record check = (Record) obj;
return getCount().compareTo(check.getCount());
}
public String toString() {
return getKey() + " " + getCount();
}
}
one easy way is to use generics :
public class Record implements Comparable<Record> {
...
public int compareTo(Record check){
return getCount().compareTo(check.getCount());
}
My guess would be null items in the array. "null instanceof Class" will return false.
This will throw the Exception:
Record[] array = new Record[] { new Record(...), null };
Arrays.sort(array);
Use generics! And an #Override annotation.

Categories