how to get list index in java with custom Model - java

I have a Model Class something like this:
public class Model {
String title, tag;
public Model() {
}
public Model(String title, String tag) {
this.title = title;
this.tag = tag;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
So I have ArrayList<Model> arr; according to my Model class
so, I want to get the Index of the tag for example -
//Let Suppose I have ArrayList Like this.
arr.add(new Model("SKYFALL","Action"));
arr.add(new Model("CASINO ROYALE","Thriller"));
//and so on.........
For example, I want the index of which have a Action tag.
I did something like this -
int index = arr.indexOf("Action");
but its index is always -1

To get Indexes of Object which contains provided tag. There can be multiple Model which has the same tag available.
public static void main(String[] args) {
ArrayList<Model> arr =new ArrayList<>();
arr.add(new Model("SKYFALL","Action"));
arr.add(new Model("CASINO ROYALE","Adventure"));
arr.add(new Model("CASINO ROYALE","Thriller"));
arr.add(new Model("CASINO ROYALE","Adventure"));
List<Integer> indexesByTag = getIndexesByTag(arr, "Adventure");;
System.out.println(indexesByTag);
// [1, 3]
}
Method to get Indexes of Objects which has provided tag available so need to return List<Integer>.
public static List<Integer> getIndexesByTag(ArrayList<Model> arr, String action){
IntStream intStream = IntStream.range(0, arr.size());
return intStream.boxed()
.map(index -> {
if(arr.get(index).getTag().equals(action)){
return index;
}
return -1;
})
.filter(index -> index!=-1)
.collect(Collectors.toList());
}
Other way without stream:
public static List<Integer> getIndexesByTag(ArrayList<Model> arr, String action){
List<Integer> indexes = new ArrayList<>();
for (int index = 0; index < arr.size(); index++) {
if(arr.get(index).getTag().equals(action)){
indexes.add(index);
}
}
return indexes;
}

You are finding the index wrong, your array list is of the array of object(Model class) while you find the index using a string.
You need to provide the object to find the index
Model actionModel = new Model("SKYFALL","Action")
arr.add(actionModel);
arr.add(new Model("CASINO ROYALE","Thriller"));
To find index
int index = arr.indexOf(actionModel);
Edit:
You can run a loop on the array list to find the index of an item
for (int i = 0; i < arr.size; i++) {
if (arr.get(i).getTag().eqauls("Action")){
index = i;
break;
}
}

If you check the indexOf method code from java library (which internally calls indexOfRange method), it return the index by making the equals method call on object.
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
In your code equals will be called on Model class object with "Action" string. Which will definitely fail the equality check.
As the solution either override the equals method to return true if either tag or title matched. But I would say that won't be a good solution because equals method should follow some contracts.
So alternatively correct should be use of Streams API here.
arr.add(new Model("SKYFALL","Action"));
arr.add(new Model("CASINO ROYALE","Thriller"));
String toMatch = "Action";
OptionalInt indexOpt = IntStream.range(0, arr.size())
.filter(i -> toMatch.equals(arr.get(i).tag))
.findFirst();
System.out.println(indexOpt.orElse(-1)); // 0 Index
Edited:
If you are using older version of Java (before Java 8), you can use normal for loop as below:
int matchedIndex = -1;
for(int i = 0; i < arr.size() ; i++) {
if(arr.get(i).getTag().equals(toMatch)) {
matchedIndex = i;
break;
}
}
So here if matchedIndex value after iteration is -1, that means there was no match. Else you will get the matched index.

Related

Set an element in an arraylist of a specific class

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

How to join a String array to a int array and sort by number (higher to lower) in Android?

I have two arrays:
int[] sinais = new int[arraySinais.length];
String[] arraySSID = new String[] { };
And I joined them into one array:
String[] arrayScan = new String[arraySinais.length];
for (int i = 0; i < arraySSID.length; i++) {
arrayScan[i] = arraySSID[i] + " " + sinais[i];
}
But now I need to sort this new array by numbers in a decreasing order and put an Image inside ListView depending the numbers, and I do not have any idea how to do this.
you can use create your own object which contains the int and the string and use arraylist to sort
First create your own custom Element (Object) which mainly consist of an int number and a String string.
public class Element implements Comparable<Element>{
private int number;
private String string;
public Element(String string, int number) {
this.number =number;
this.string = string;
}
//create custom constructors if its allowed to define an element without a number or string
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
#Override
public int compareTo(Element e) {
return number - e.number;
}
}
Implement comparable as above to sort depending on the number value, but keep in my mind that your element won't sort stand alone strings.
If you want to sort your list depending on strings if a number doesn't exist use this implementation of comparTo() method:
#Override
public int compareTo(Element e) {
if(e.number != 0) return number - e.number;
return string.compareTo(e.string);
}
While using implement a List of elements and use Collections sort() method and you are good to go:
List<Element> list = new ArrayList<>();
//add Elements
Collections.sort(list);
I used the method below, by Bubble Sort, and solve my problem:
> for (int i = Sinais.length; i >= 1; i--){
> for (int j = 1; j < i; j++){
> if (Sinais[j-1]<Sinais[j]){
> int aux = Sinais[j];
> String aux2 = ArraySSID[j];
> Sinais[j] = Sinais[j-1];
> ArraySSID[j] = ArraySSID[j-1];
> Sinais[j-1] = aux;
> ArraySSID[j-1] = aux2;
> }
> }
> }

returning the position of an array

I am trying to create a find method, that will check every entry in my PhoneDirectory, and return the position of the name that matches the name given in the parameter. This is what currently have:
private String find(String name) {
for (DirectoryEntry x : theDirectory) {
if (x.getName().equals(name)) {
return x.getName();
}
}
return null;
}
However I will be calling my find function from within other methods that don't necessarily want the name returned, but instead the number attached to the name, (each DirectoryEntry has a name and a telno).
Any help regarding how to return the position of the array instead of just the matching name, would be much appreciated.
you can take a couter to count the postion
private int find(String name) {
int i = 0;
for (DirectoryEntry x : theDirectory) {
if (x.getName().equals(name)) {
return i;
}
i++;
}
return -1; // returning -1 if not found
}
or you can use normal for loop instead of foreach
private String find(String name) {
int k=0;
for (DirectoryEntry x : theDirectory) {
if (x.getName().equals(name)) {
k++;
return x.getName();
}
}
//k will give you pos
return null;
}
If you want the position in the array, use a regular loop instead of a foreach loop.
for (int i=0;i<theDirectory.length;i++) {
DirectoryEntry x = theDirectory[i];
if (x.getName().equals(name)) {
return i;
}
}
Depending on the type of your theDirectory-field you could use an own counter up to its length:
private int find(String name) {
for (int i = 0; i < theDirectory.length(); i++) {
DirectoryEntry x = theDirectory[i]; //If it is an Array; for Lists use get etc...
if (x.getName().equals(name)) {
return i;
}
}
return -1;
}
Why not to avoid reinventing the wheel and use Guava instead:
private int find(String name) {
return Iterables.indexOf(theDirectory, new Predicate<DirectoryEntry>() {
public boolean apply(DirectoryEntry de) {
return de.getName().equals(name);
}
});
}

Sorting using comparable

Intro
My code to do a custom sort by using Comparable is not work the way I want it to. I'm basically taking an Array of directories and sorting them by:
First number of directories, the fewer comes first.
If it's a tie alphabetically.
The problem
An example of an input you be:
["/", "/usr/", "/usr/local/", "/usr/local/bin/", "/games/",
"/games/snake/", "/homework/", "/temp/downloads/" ]
Which should return this:
["/", "/games/", "/homework/", "/usr/", "/games/snake/",
"/temp/downloads/", "/usr/local/", "/usr/local/bin/" ]
But for some reason my code is return this:
["/", "/usr/", "/games/", "/homework/", "/usr/local/",
"/games/snake/", "/usr/local/bin/", "/temp/downloads/" ]
My code [edited with comments]
import java.util.*;
public class Dirsort { public String[] sort(String[] dirs) {
//Creates Array list containing Sort object
ArrayList<Sort> mySort = new ArrayList<Sort>();
//Loop that gets the 3 needed values for sorting
for (String d: dirs){
String [] l = d.split("/");//String array for alphabetical comparison
int di = d.length();//Length of array for sorting by number of directories
mySort.add(new Sort(di,l,d));//adds Sort object to arraylist (note d (the entire directory) is needed for the toString)
}
Collections.sort(mySort);//sorts according to compareTo
String [] ans = new String [mySort.size()];//Creates a new string array that will be returned
int count = 0;//to keep track of where we are in the loop for appending
for (Sort s: mySort){
ans[count] = s.toString();
count++;
}
return ans;
}
class Sort implements Comparable<Sort>{
private int d;//number of directories
private String [] arr;//array of strings of names of directories
private String dir;//full directory as string for toString
//Constructor
public Sort(int myD, String [] myArr, String myDir){
d = myD;
arr = myArr;
dir = myDir;
}
//toString
public String toString(){
return dir;
}
#Override
public int compareTo(Sort arg0) {
// TODO Auto-generated method stub
//If they are the same return 0
if (this.equals(arg0)){
return 0;
}
//if the directories are empty
if("/".equals(arg0.dir)){
return 1;
}
if ("/".equals(this.dir)){
return -1;
}
//If they are not the same length the shorter one comes first
if (this.d != arg0.d){
return this.d - arg0.d;
}
//If they are the same length, compare them alphabetically
else{
for (int i = 0; i < arg0.d; i++){
if (!this.arr[i].equals(arg0.arr[i])){
return this.arr[i].compareTo(arg0.arr[i]);
}
}
}
return 0;
}
}
}
The bug is here:
for (String d: dirs){
String [] l = d.split("/");
int di = d.length(); // <- here
mySort.add(new Sort(di,l,d));
}
Because there you are comparing the length of the entire directory String, not the number of 'folders' in the directory. That's why "/usr/" comes before "/homework/", for example, because:
"/usr/".length() == 5
"/homework/".length() == 10
I believe what you wanted was this, using the length of the split:
int di = l.length;
Then the output is:
/
/games/
/homework/
/usr/
/games/snake/
/temp/downloads/
/usr/local/
/usr/local/bin/
There's another small bug though (possibly), which is that calling split on a String that starts with the delimiter will result in an empty String at the beginning.
IE:
"/usr/".split("/") == { "", "usr" }
So you might want to do something about that. Though here it means that all of them start with the empty String so it doesn't end up with an effect on the way you're doing the comparison.
And as a side note, it's also true what #JBNizet is suggesting that giving your variables more meaningful names helps a lot here. fullDir.length() and splitDir.length would have made this much easier to spot (and it may have never happened in the first place).
Here's a fixed version of your code, which handles the case where both directories are "/", which removes the unnecessary, and incorrectly passed length of the parts array, and which uses more meaningful variable names:
public class Dirsort {
public static void main(String[] args) {
String[] input = new String[] {
"/",
"/usr/",
"/usr/local/",
"/usr/local/bin/",
"/games/",
"/games/snake/",
"/homework/",
"/temp/downloads/"
};
String[] result = new Dirsort().sort(input);
System.out.println("result = " + Arrays.toString(result));
}
public String[] sort(String[] dirs) {
ArrayList<Sort> sorts = new ArrayList<Sort>();
for (String dir : dirs) {
String[] parts = dir.split("/");
sorts.add(new Sort(parts, dir));
}
Collections.sort(sorts);
String[] result = new String[sorts.size()];
int count = 0;
for (Sort sort: sorts) {
result[count] = sort.toString();
count++;
}
return result;
}
class Sort implements Comparable<Sort> {
private String[] parts;
private String dir;
public Sort(String[] parts, String dir) {
this.parts = parts;
this.dir = dir;
}
public String toString(){
return dir;
}
#Override
public int compareTo(Sort other) {
if (this.equals(other)){
return 0;
}
if("/".equals(other.dir) && "/".equals(dir)) {
return 0;
}
if("/".equals(other.dir)){
return 1;
}
if ("/".equals(this.dir)){
return -1;
}
if (this.parts.length != other.parts.length){
return this.parts.length - other.parts.length;
}
else {
for (int i = 0; i < other.parts.length; i++){
if (!this.parts[i].equals(other.parts[i])){
return this.parts[i].compareTo(other.parts[i]);
}
}
}
return 0;
}
}
}
I spotted the problem by simply using my debugger and make it display the value of all the variables.
public class Disort
{
public static String[] sort(String[] dirs)
{
ArrayList<Path> mySort = new ArrayList<Path>();
Path pathDir;
for(String dir : dirs){
pathDir = Paths.get(dir);
// check if directory exists
if(Files.isDirectory(pathDir)){
mySort.add(pathDir);
}
}
// sort the ArrayList according a personalized comparator
Collections.sort(mySort, new Comparator<Path>(){
#Override
public int compare(Path o1, Path o2)
{
if(o1.getNameCount() < o2.getNameCount()){
return -1;
}
else if(o1.getNameCount() > o2.getNameCount()){
return 1;
}
else{
return o1.compareTo(o2);
}
}
});
// to return a String[] but it will better to return a ArrayList<Path>
String[] result = new String[mySort.size()];
for(int i = 0; i < result.length; i++){
result[i] = mySort.get(i).toString();
}
return result;
}
}

merging two objects of strings. java

I have an assignment that requires me to make ordered string list objects.
i currently have 2 ordered string lists, each with 7 string values in them.
im trying to create a method that merges list myList and yourList into a combined list combinedList.
here is what i have so far.
public boolean merge(OrderedStringList myList, OrderedStringList yourList){
int index;
String value;
for (index = 0;index < numUsed; index++){
value = myList.storage[index];
combinedList.insert(value);
}
for (index = 0;index < numUsed; index++){
value = yourList.storage[index];
combinedList.insert(value);
}
}
i declare the object combinedList in my main, and it doesnt recognize it in my orderedStringList.class
the insert function will insert strings into alphabetical order.
If you declared the combinedList inside your main function, it is accessible only inside the main function.
What you should do is create the combinedList inside the above function and return the result to the calling function i.e. your main function.
Where exactly is combinedList declared? Perhaps you should declare it outside outside your method so that all the methods can access it.
public class Merger {
private OrderedStringList combinedList; // This is a field
private int numUsed;
public static void main(){
new Merger().merge(new OrderedStringList(),new OrderedStringList());
}
public boolean merge(OrderedStringList myList, OrderedStringList yourList){
int index;
String value;
for (index = 0;index < numUsed; index++){
value = myList.storage[index];
combinedList.insert(value);
}
for (index = 0;index < numUsed; index++){
value = yourList.storage[index];
combinedList.insert(value);
}
return false;
}
}
class OrderedStringList {
public String[] storage;
public void insert(String value) {
// TODO Auto-generated method stub
}
}
Found out how to fix my problem. I just called the insert function based on the amount of strings that were in each list, and added them to the new combined list.
public boolean merge(OrderedStringList myList, OrderedStringList yourList) {
boolean result = false;
int index;
for (index = 0; index < myList.numUsed; index++) {
Insert(myList.storage[index]);
result = true;
}
for (index = 0; index < yourList.numUsed; index++) {
Insert(yourList.storage[index]);
result = true;
}
return result;
}

Categories