Set an element in an arraylist of a specific class - java

In my program I have a pair class:
class Pair {
public int ind = 0;
public String letter = "";
public Pair(int a, String b) {
ind = a; //index
letter = b;
}
}
how do I set the index (ind) of an element in an arraylist of Pairs? I have tried
RightMotor.ind.set(j, i);
and
LeftMotor.set(j, i).ind;
but they don't seem to work.

First you need to 'get' the Pair instance, like:
Pair pair = LeftMotor.get(i);
then you can change its fields:
pair.ind = j;
This can also be done in one line:
LeftMotor.get(i).ind = j;
Hint 1: this is not changing the index (position) of the instance in the list, LeftMotor.get(i) will still return the same element. i and ind are two completely disjunct values.
Hint 2: normally it is better to have private fields and have a method (setter) to change the fields (encapsulation):
class Pair {
private int ind = 0;
private String letter = "";
public Pair(int a, String b) {
ind = a; //index
letter = b;
}
public void setInd(int newInd) {
ind = newInd;
}
}
Hint 3: just to be clear, just because it is called ind it is not the index (position) of the list. It is a whole different question if you want to change the order of the elements in the list.

You want to make those instance variables private, then getters/setters to access/modify them. This allows you to safely and securely manipulate the data with a reduced chance of bleedover (which can crash your program or cause unintended consequences).
Within your class:
class Pair {
private int ind = 0;
private String letter = "";
public Pair(int index, String letter) {
ind = index;
letter = letter;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getLetter() {
return this.letter;
}
public void setLetter(String letter) {
this.letter = letter;
}
public void setIndexAndLetter(int index, String letter) {
this.index = index;
this.letter = letter;
}
}
Elsewhere in your program:
Pair rightMotor = new Pair(1, "a");
Pair leftMotor = new Pair(2, "b");
Pair middleMotor = new Pair(0, "");
rightMotor.setInd(3);
leftMotor.setLetter("d");
middleMotor.setIndAndLetter(rightMotor.getInd() + leftMotor.getInd(), "z");

You have to create a Pair instance using the Pair constructor before adding it to the ArrayList:
RightMotor.add(new Pair(i,j)); // assuming i is an int and j is a String
If you want to replace the Pair stored in a given index use:
RightMotor.set(index,new Pair(i,j));
If you want to change an existing Pair stored in the ArrayList:
RightMotor.get(index).setInd(newValue);
This will require a setter method in your Pair class:
public void setInd (int i) {
ind = i;
}

So I think that you could solve this in a couple of different ways... however I think I know what you are trying to do.... I feel like you are trying to keep the ArrayList and the Pair index synchronized... either way you will need a helper method to accomplish this. I agree with hendripd that you should use private variables and utilize the getters and setters. However this is my solution.
Pair:
public class Pair implements Comparable<Pair> {
private int index = 0;
private String letter = "";
public Pair(int index, String letter) {
this.index = index;
this.letter = letter;
}
public Pair(Pair pair) {
this.index = pair.getIndex();
this.letter = pair.getLetter();
}
#Override
public int compareTo(Pair pair) {
if (this.index > pair.index) {
return 1;
} else if (this.index < pair.index) {
return -1;
} else {
return 0;
}
}
#Override
public String toString() {
return this.index + " " + this.letter;
}
public int getIndex() {
return this.index;
}
public String getLetter() {
return this.letter;
}
public void setIndex(int index) {
this.index = index;
}
public void setLetter(String letter) {
this.letter = letter;
}
}
Main:
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static ArrayList<Pair> rightMotor;
public static void main(String[] args) {
rightMotor = new ArrayList<Pair>();
rightMotor.add(new Pair(0, "a"));
rightMotor.add(new Pair(1, "b"));
setIndex(rightMotor, 0, 1);
// If you choose to go with the second option utilizing Comparable<Pair>
// Collections.sort(rightMotor);
for (Pair pair : rightMotor) {
System.out.println(pair.toString());
}
}
public static void setIndex(ArrayList<Pair> motor, int oldIndex, int newIndex) {
Pair tempPair = new Pair(motor.get(oldIndex));
if (oldIndex < newIndex) {
for (int i = oldIndex; i < newIndex; i++) {
motor.set(i, motor.get(i + 1));
motor.get(i).setIndex(i);
}
} else if (oldIndex > newIndex) {
for (int i = oldIndex; i > newIndex; i--) {
motor.set(i, motor.get(i - 1));
motor.get(i).setIndex(i);
}
}
tempPair.setIndex(newIndex);
motor.set(newIndex, tempPair);
}
}
Note that the Pair class implements comparable... you could use Collections.Sort(rightMotor) which then you would only need to fix the indexes of the instances... i.e.
public static void setIndex(ArrayList<Pair> motor, int oldIndex, int newIndex) {
motor.get(oldIndex).setIndex(newIndex);
if (oldIndex < newIndex) {
for (int i = oldIndex; i < newIndex; i++) {
motor.get(i + 1).setIndex(i);
}
} else if (oldIndex > newIndex) {
for (int i = oldIndex; i > newIndex; i--) {
motor.get(i - 1).setIndex(i);
}
}
}
Or... you can use the original one I posted which also handles the sorting at the same time. This keeps your Arraylist in numerical order by index either way.
Test casing:
rightMotor.add(new Pair(0, "a"));
rightMotor.add(new Pair(1, "b"));
rightMotor.add(new Pair(2, "c"));
rightMotor.add(new Pair(3, "d"));
rightMotor.add(new Pair(4, "e"));
rightMotor.add(new Pair(5, "f"));
setIndex(rightMotor, 0, 1);
setIndex(rightMotor, 3, 1);
setIndex(rightMotor, 4, 3);
outputs this result:
0 b
1 d
2 a
3 e
4 c
5 f

Related

Constraining all combinations of an array-list

I know similar questions have been asked before but I have found the answers confusing. I am trying to make a program that will find every combination of an array-list with no repetitions and only of the maximum size. If the list has 4 items it should print out only the combinations with all 4 items present. This is what I have so far:
public main(){
UI.initialise();
UI.addButton("Test", this::testCreate);
UI.addButton("Quit", UI::quit);
}
public void createCombinations(ArrayList<String> list, String s, int depth) {
if (depth == 0) {
return;
}
depth --;
for (int i = 0; i < list.size(); i++) {
if (this.constrain(s + "_" + list.get(i), list.size())) {
UI.println(s + "_" + list.get(i));
}
createCombinations(list, s + "_" + list.get(i), depth);
}
}
public void testCreate() {
ArrayList<String> n = new ArrayList<String>();
n.add("A"); n.add("B"); n.add("C"); n.add("D");
this.createCombinations(n , "", n.size());
}
public boolean constrain(String s, int size) {
// Constrain to only the maximum length
if ((s.length() != size*2)) {
return false;
}
// Constrain to only combinations without repeats
Scanner scan = new Scanner(s).useDelimiter("_");
ArrayList<String> usedTokens = new ArrayList<String>();
String token;
while (scan.hasNext()) {
token = scan.next();
if (usedTokens.contains(token)) {
return false;
} else {
usedTokens.add(token);
}
}
// If we fully iterate over the loop then there are no repitions
return true;
}
public static void main(String[] args){
main obj = new main();
}
This prints out the following which is correct:
_A_B_C_D
_A_B_D_C
_A_C_B_D
_A_C_D_B
_A_D_B_C
_A_D_C_B
_B_A_C_D
_B_A_D_C
_B_C_A_D
_B_C_D_A
_B_D_A_C
_B_D_C_A
_C_A_B_D
_C_A_D_B
_C_B_A_D
_C_B_D_A
_C_D_A_B
_C_D_B_A
_D_A_B_C
_D_A_C_B
_D_B_A_C
_D_B_C_A
_D_C_A_B
_D_C_B_A
This works for small lists but is very inefficient for larger ones. I am aware that what I have done is completely wrong but I want to learn the correct way. Any help is really appreciated. Thanks in advance.
P.S. This is not homework, just for interest although I am a new CS student (if it wasn't obvious).
Implementing Heap's algorithm in Java:
import java.util.Arrays;
public class Main {
public static void swap(final Object[] array, final int index1, final int index2) {
final Object tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
}
public static void printPermutations_HeapsAlgorithm(final int n, final Object[] array) {
final int[] c = new int[n];
for (int i = 0; i < c.length; ++i)
c[i] = 0;
System.out.println(Arrays.toString(array)); //Consume first permutation.
int i=0;
while (i < n) {
if (c[i] < i) {
if ((i & 1) == 0)
swap(array, 0, i);
else
swap(array, c[i], i);
System.out.println(Arrays.toString(array)); //Consume permutation.
++c[i];
i=0;
}
else
c[i++] = 0;
}
}
public static void main(final String[] args) {
printPermutations_HeapsAlgorithm(4, new Character[]{'A', 'B', 'C', 'D'});
}
}
Possible duplicate of this.

How to sort Enum and add to an array

I have an enum
Customer("Customer"),
BankName("Bank Name"),
AccountNumber("Account Number"),
Amount("Available Amount");
I have an array of ints, that contains the right order
private static int[] realOrder;
I have a method that sorts enum in the right order
public static void configureColumns(Column... newOrder)
{
realOrder = new int[values().length];
for (Column column : values())
{
realOrder[column.ordinal()] = -1;
boolean isFound = false;
for (int i = 0; i < newOrder.length; i++)
{
if (column == newOrder[i])
{
if (isFound)
{
throw new IllegalArgumentException("Column '" + column.columnName + "' is already configured.");
}
realOrder[column.ordinal()] = i;
isFound = true;
}
}
}
}
And when i call that method like that
Column.configureColumns(Column.Amount, Column.AccountNumber, Column.BankName);
I want it to be printed
* Available Amount
* Account Number
* Bank Name
I have a method, that returns a linked list according to the realOrder indexes
public static List<Column> getVisibleColumns()
{
List<Column> result = new LinkedList<>();
int index;
for(int i = 0; i < realOrder.length; i++)
{
if(realOrder[i]!=-1)
{
index = realOrder[i];
result.add(index, Column.values()[index]);
}
}
return result;
}
But i get java.lang.IndexOutOfBoundsException: Index: 2, Size: 0 because i should start from 0 to fill the array. If i sort the realOrder array from smallest to greatest, it works, but not in way it expected. How can i solve it?
It seems you want getVisibleColumns() to return the values exactly as they were given to configureColumns(), so why not just remember that?
public enum Column {
Customer("Customer"),
BankName("Bank Name"),
AccountNumber("Account Number"),
Amount("Available Amount");
private static Column[] realOrder;
private final String columnName;
private Column(String columnName) {
this.columnName = columnName;
}
public String getColumnName() {
return this.columnName;
}
public static void configureColumns(Column... newOrder) {
realOrder = newOrder.clone();
}
public static List<Column> getVisibleColumns() {
return Collections.unmodifiableList(Arrays.asList(realOrder));
}
}
If you also need a to know the order index of a particular Column, don't create a separate array to store that. Just add an extra field to the enum:
private int orderIndex = -1;
Then update the value when configuring:
public static void configureColumns(Column... newOrder) {
realOrder = newOrder.clone();
for (Column column : values())
column.orderIndex = -1;
for (int i = 0; i < newOrder.length; i++)
newOrder[i].orderIndex = i;
}

Returning Elements From ArrayList Alphabetically

I'm working on a program to manipulate chemical formulae, and I'm writing a method which needs to loop through an ArrayList called "terms" and return the first one alphabetically.
e.g. terms = {Term('H',4),Term('C',2),Term('H',4),Term('C',1)} would return Term('C',2)
I've written this code so far but it's not working. I'm a real beginner to the Java language.
public Term nextElement()
{
int i = 0;
for (i = 0; i < terms.size()-1; i++)
{
int j = 1;
while (i + j <= terms.size())
if (terms.get(i).getElement() > terms.get(i+j).getElement())
{
terms.remove(i+j++);
return terms.get(i);
}
}
return null;
}
I'd appreciate any ideas or suggestions to solve this problem. Thanks!
You have two options here:
Let your Term class implement Comparable interface and override its compareTo() method. Then you can use Collections.sort(listOfTerms) to sort them and loop through.
Add class TermComparator which implements Comparator interface, use Collections.sort(listOfTerms, new TermComparator()) and loops through the sorted list.
1- you can implement Comparable and override compareTo()
int compareTo(Object obj){
Term term = (Term)obj;
if(term.getElement < this.getElement())
return 1;
else if (term.getElement == this.getElement())
return 0;
else
return -1;
}
then use
Collection.sort(terms);
2-
public Term nextElement()
{
char minElement = 'Z';
int index = 0;
for (int i = 0; i < terms.size(); i++)
{
if (terms.get(i).getElement() < minElement)
{
minElement = terms.get(i).getElement();
index = i;
}
}
Term temp = terms.get(index);
terms.remove(index)
return temp;
}
use Collections.sort(terms);it will arrange the list alphabetically.
This is what you need to do:
List<Term> terms = //your list
Collections.sort(terms, new Comparator<Term>() {
#Override
public int compare(Term t1, Term t2) {
return t1.getElement().compareTo(t2.getElement());
}
});
CODE:
public class CodeSample {
public static void main(String[] args) {
List<Term> terms=new ArrayList<Term>();
terms.add(new Term('H',4));
terms.add(new Term('C',2));
terms.add(new Term('H',4));
terms.add(new Term('C',1));
System.out.println("Before Sorting");
for(Term term:terms){
System.out.print(term.toString().concat(" "));
}
Collections.sort(terms,new Comparator<Term>() {
#Override
public int compare(Term object1, Term object2) {
if (object1.getElement() != object2.getElement()) {
return object1.getElement() - object2.getElement();
} else {
return object2.getCount() - object1.getCount();
}
}
});
//Sorted terms
System.out.println("After Sorting");
for(Term term:terms){
System.out.print(term.toString().concat(" "));
}
}
public static class Term{
private char element;
private int count;
public Term(char element, int count) {
super();
this.element = element;
this.count = count;
}
public char getElement() {
return element;
}
public int getCount() {
return count;
}
#Override
public String toString() {
return "Term [element=" + element + ", count=" + count + "]";
}
}
}
OUTPUT:
Before Sorting
Term [element=H, count=4] Term [element=C, count=2] Term [element=H, count=4] Term [element=C, count=1]
After Sorting
Term [element=C, count=2] Term [element=C, count=1] Term [element=H, count=4] Term [element=H, count=4]

Altering the value of k in kNN algorithm - Java

I have applied the KNN algorithm for classifying handwritten digits. the digits are in vector format initially 8*8, and stretched to form a vector 1*64..
As it stands my code applies the kNN algorithm but only using k = 1. I'm not entirely sure how to alter the value k after attempting a couple of things I kept getting thrown errors. If anyone could help push me in the right direction it would be really appreciated. The training dataset can be found here and the validation set here.
ImageMatrix.java
import java.util.*;
public class ImageMatrix {
private int[] data;
private int classCode;
private int curData;
public ImageMatrix(int[] data, int classCode) {
assert data.length == 64; //maximum array length of 64
this.data = data;
this.classCode = classCode;
}
public String toString() {
return "Class Code: " + classCode + " Data :" + Arrays.toString(data) + "\n"; //outputs readable
}
public int[] getData() {
return data;
}
public int getClassCode() {
return classCode;
}
public int getCurData() {
return curData;
}
}
ImageMatrixDB.java
import java.util.*;
import java.io.*;
import java.util.ArrayList;
public class ImageMatrixDB implements Iterable<ImageMatrix> {
private List<ImageMatrix> list = new ArrayList<ImageMatrix>();
public ImageMatrixDB load(String f) throws IOException {
try (
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr)) {
String line = null;
while((line = br.readLine()) != null) {
int lastComma = line.lastIndexOf(',');
int classCode = Integer.parseInt(line.substring(1 + lastComma));
int[] data = Arrays.stream(line.substring(0, lastComma).split(","))
.mapToInt(Integer::parseInt)
.toArray();
ImageMatrix matrix = new ImageMatrix(data, classCode); // Classcode->100% when 0 -> 0% when 1 - 9..
list.add(matrix);
}
}
return this;
}
public void printResults(){ //output results
for(ImageMatrix matrix: list){
System.out.println(matrix);
}
}
public Iterator<ImageMatrix> iterator() {
return this.list.iterator();
}
/// kNN implementation ///
public static int distance(int[] a, int[] b) {
int sum = 0;
for(int i = 0; i < a.length; i++) {
sum += (a[i] - b[i]) * (a[i] - b[i]);
}
return (int)Math.sqrt(sum);
}
public static int classify(ImageMatrixDB trainingSet, int[] curData) {
int label = 0, bestDistance = Integer.MAX_VALUE;
for(ImageMatrix matrix: trainingSet) {
int dist = distance(matrix.getData(), curData);
if(dist < bestDistance) {
bestDistance = dist;
label = matrix.getClassCode();
}
}
return label;
}
public int size() {
return list.size(); //returns size of the list
}
public static void main(String[] argv) throws IOException {
ImageMatrixDB trainingSet = new ImageMatrixDB();
ImageMatrixDB validationSet = new ImageMatrixDB();
trainingSet.load("cw2DataSet1.csv");
validationSet.load("cw2DataSet2.csv");
int numCorrect = 0;
for(ImageMatrix matrix:validationSet) {
if(classify(trainingSet, matrix.getData()) == matrix.getClassCode()) numCorrect++;
} //285 correct
System.out.println("Accuracy: " + (double)numCorrect / validationSet.size() * 100 + "%");
System.out.println();
}
In the for loop of classify you are trying to find the training example that is closest to a test point. You need to switch that with a code that finds K of the training points that is the closest to the test data. Then you should call getClassCode for each of those K points and find the majority(i.e. the most frequent) of the class codes among them. classify will then return the major class code you found.
You may break the ties (i.e. having 2+ most frequent class codes assigned to equal number of training data) in any way that suits your need.
I am really inexperienced in Java, but just by looking around the language reference, I came up with the implementation below.
public static int classify(ImageMatrixDB trainingSet, int[] curData, int k) {
int label = 0, bestDistance = Integer.MAX_VALUE;
int[][] distances = new int[trainingSet.size()][2];
int i=0;
// Place distances in an array to be sorted
for(ImageMatrix matrix: trainingSet) {
distances[i][0] = distance(matrix.getData(), curData);
distances[i][1] = matrix.getClassCode();
i++;
}
Arrays.sort(distances, (int[] lhs, int[] rhs) -> lhs[0]-rhs[0]);
// Find frequencies of each class code
i = 0;
Map<Integer,Integer> majorityMap;
majorityMap = new HashMap<Integer,Integer>();
while(i < k) {
if( majorityMap.containsKey( distances[i][1] ) ) {
int currentValue = majorityMap.get(distances[i][1]);
majorityMap.put(distances[i][1], currentValue + 1);
}
else {
majorityMap.put(distances[i][1], 1);
}
++i;
}
// Find the class code with the highest frequency
int maxVal = -1;
for (Entry<Integer, Integer> entry: majorityMap.entrySet()) {
int entryVal = entry.getValue();
if(entryVal > maxVal) {
maxVal = entryVal;
label = entry.getKey();
}
}
return label;
}
All you need to do is adding K as a parameter. Keep in mind, however, that the code above does not handle ties in a particular way.

InventoryItem.java uses unchecked or unsafe operations

I'm learning about comparable and am implementing it in my Inventory class. However when I go to compile the code, the compiler gives an error.
InventoryItem.java uses unchecked or unsafe operations.
Can anyone please help me out. What is wrong with my code and what can I do to fix this issue. Thank you for your help in advance.
class InventoryItem implements Comparable<InventoryItem>
{
private String name;
private int uniqueItemID;
public InventoryItem()
{
name = " ";
uniqueItemID = 0;
}
public InventoryItem(String newName, int newItemID)
{
name = newName;
uniqueItemID = newItemID;
}
public InventoryItem(InventoryItem i)
{
name = i.name;
uniqueItemID = i.uniqueItemID;
}
public void setName(String newName)
{
name = newName;
}
public void setItemID(int newItemID)
{
uniqueItemID = newItemID;
}
public int getItemID()
{
return uniqueItemID;
}
public String getName()
{
return name;
}
public int compareTo(InventoryItem i)
{
int anotherUniqueID = i.getItemID();
return (this.uniqueItemID - anotherUniqueID);
}
public static void sort(Comparable[] a, int numberUsed)
{
int index, indexOfNextSmallest;
for(index = 0; index < numberUsed - 1; index++)
{
indexOfNextSmallest = indexOfSmallest(index, a, numberUsed);
interchange(index, indexOfNextSmallest, a);
}
}
private static int indexOfSmallest(int startIndex, Comparable[] a, int numberUsed)
{
Comparable min = a[startIndex];
int indexOfMin = startIndex;
int index;
for(index = startIndex + 1; index < numberUsed; index++)
{
if(a[index].compareTo(min) < 0)
{
min = a[index];
indexOfMin = index;
}
}
return indexOfMin;
}
private static void interchange(int i, int j, Comparable[] a)
{
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
public class InventoryItemTester
{
public static void main(String [] args)
{
InventoryItem[] items = new InventoryItem[3];
items[0] = new InventoryItem("Pens", 2);
items[1] = new InventoryItem("Pencils", 3);
items[2] = new InventoryItem("Notebooks", 1);
System.out.println("Before sorting");
System.out.println(items[0]);
System.out.println(items[1]);
System.out.println(items[2]);
InventoryItem.sort(items, items.length);
System.out.println("After sorting");
System.out.println(items[0]);
System.out.println(items[1]);
System.out.println(items[2]);
}
}
At a guess I'd say this line is causing the issue (Your compiler tells you exactly which line is the problem, this might be useful to include in your next question):
private static int indexOfSmallest(int startIndex, Comparable[] a, int numberUsed)
{
Comparable min = a[startIndex];
int indexOfMin = startIndex;
int index;
for(index = startIndex + 1; index < numberUsed; index++)
{
here==========> if(a[index].compareTo(min) < 0)
{
You are calling compareTo with a InventoryItem where it is expecting an Object. You could add a #SuppressWarnings annotation which would make it go away :)
The basic idea of Comparable and Comparator is they apply a sorting order to an Object so that the standard JDK Collections objects can do all the hard work for you.
In your case your comparesTo method does the correct thing, however I'm not sure if this is good planning or good luck, so things to note:
InventoryItem.comparesTo method needs to evaluate the current instance to the provided instance and return an integer signifying the ordering, -1 means the instance (ie this) should be ordered before the argument, 0 means they are the same and 1 means the instance is after the argument. Something like this lets the JDK do all the hard work for you
public int compareTo(InventoryItem i)
{
return Integer.valueOf(this.uniqueItemID).compareTo(i.uniqueItemID);
}
In order to use Comparable all you really need to do is implement it and then use the standard JDK Collections classes to do all the heavy lifting for you, eg:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class InventoryItemTest
{
public static void main(String [] args)
{
List<InventoryItem> items = new ArrayList<InventoryItem>();
items.add(new InventoryItem("Pens", 2));
items.add(new InventoryItem("Pencils", 3));
items.add(new InventoryItem("Notebooks", 1));
System.out.println("Before sorting");
System.out.println(items);
Collections.sort(items);
System.out.println("After sorting");
System.out.println(items);
}
}
I realise this might not be as much fun as writing your own sorting algorithms but if you want to do that with no compiler warnings then you need to start looking at generics

Categories