I have
String selectedName = "ABC";
List<object> pgetName;
where object has variables such as id, name, version
I want to do the equivalent of
int first = pgetName.indexOf(selectedName);
int last = pgetName.lastIndexOf(selectedName);
as used for simple String Arrays. I've tried
int first = pgetName.getProperty("name").indexOf(processToStart);
and
int first = pgetName[].getName().indexOf(processToStart);
for example but they don't work. How do I do what I want to do? This is advanced Java for me being a noob...
Thanks in advance,
Here's an other approach (might be a little overkill but it shows you an other way). The idea is to override the indexOf and lastIndexOf method so it would verify against your field "name":
private static class TestObject {
String id, name, version;
public TestObject(String id, String name, String version) {
super();
this.id = id;
this.name = name;
this.version = version;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
}
public static void main(String[] args) {
List<TestObject> pgetName = new ArrayList<TestObject>() {
#Override
public int indexOf(Object o) {
if (o == null || this.isEmpty()) {
return -1;
}
int counter=0;
for (TestObject current : this) {
if (o.equals(current.getName())) {
return counter;
}
counter++;
}
return -1;
}
#Override
public int lastIndexOf(Object o) {
if (o == null || this.isEmpty()) {
return -1;
}
for (int i=this.size()-1; i>=0;i--) {
TestObject current = get(i);
if (o.equals(current.getName())) {
return i;
}
}
return -1;
}
};
pgetName.add(new TestObject("1", "name1", "ver1"));
pgetName.add(new TestObject("2", "name2", "ver2"));
pgetName.add(new TestObject("3", "name3", "ver3"));
pgetName.add(new TestObject("4", "name1", "ver4"));
int first = pgetName.indexOf("name1");
int last = pgetName.lastIndexOf("name1");
System.out.println("First: " + first + " - Last: " + last);
}
Result is:
First: 0 - Last: 3
For any Java object you can override the methods equals and hashCode (this is not really used but it is generally a good practice to implement both methods) in order to use the indexOf and lastIndexOf functions of java.util.List.
The contextual menu of eclipse generates a default implementation of both methods, letting you choose on which field the comparison should be done. Give it a try.
After the implementation of the methods above, you can use indexOf on List.
If I understand your question, you want to "find the index of an Object where one of the properties of the object is a specific value".
This isn't directly possible in Java (or most languages FWIW). You can achieve it pretty simply with a for loop, however:
public MyObject findObjectByName(MyObject[] objects, String name) {
for (MyObject object: objects) {
if (object.name.equal(name) {
return object;
}
}
return null;
}
If you want to find the index, you can do something similar:
public int findObjectIndex(MyObject[] objects, String name) {
for (int i = 0; i < objects.length; ++i)
if (objects[i].name.equal(name) {
return i;
}
}
return -1;
}
Now, this is the most naive approach you can take, and is often, but not always, the best approach. If you have a large number of objects, and you need to look up a lot by name, then you could be better off building an index once, and then look them up by the index:
public class MyObjectIndex {
final Map<String, MyObject> byName = new HashMap<String, MyObject>();
public MyObjectIndex(MyObject[] objects) {
for (MyObject object: objects) {
byName.put(object.getName(), object);
}
}
public getMyObjectWithName(String name) {
return byName.get(name);
}
}
Related
This is my VO
public class SomeVO {
private String name;
private String usageCount;
private String numberofReturns;
private String trendNumber;
private String nonTrendNumber;
private String trendType;
private String auditType;
public SomeVO(String name,String usageCount,String numberofReturns,String trendNumber,String nonTrendNumber,String trendType,String auditType){
this.name = name;
this.usageCount = usageCount;
this.numberofReturns = numberofReturns;
this.trendNumber = trendNumber;
this.nonTrendNumber = nonTrendNumber;
this.trendType = trendType;
this.auditType = auditType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsageCount() {
return usageCount;
}
public void setUsageCount(String usageCount) {
this.usageCount = usageCount;
}
public String getNumberofReturns() {
return numberofReturns;
}
public void setNumberofReturns(String numberofReturns) {
this.numberofReturns = numberofReturns;
}
public String getTrendNumber() {
return trendNumber;
}
public void setTrendNumber(String trendNumber) {
this.trendNumber = trendNumber;
}
public String getNonTrendNumber() {
return nonTrendNumber;
}
public void setNonTrendNumber(String nonTrendNumber) {
this.nonTrendNumber = nonTrendNumber;
}
public String getTrendType() {
return trendType;
}
public void setTrendType(String trendType) {
this.trendType = trendType;
}
public String getAuditType() {
return auditType;
}
public void setAuditType(String auditType) {
this.auditType = auditType;
}
}
Here is my values
List<SomeVO> myList = new ArrayList<SomeVO>();
SomeVO some = new SomeVO("A","0","0","123","123","Trend","AuditX");
myList.add(some);
some = new SomeVO("B","1","1","234","234","Non trend","AuditX");
myList.add(some);
some = new SomeVO("C","0","2","345","345","Trend","AuditX");
myList.add(some);
some = new SomeVO("D","2","3","546","546","Trend","AuditX");
myList.add(some);
some = new SomeVO("E","2","4","678","678","Non trend","AuditX");
myList.add(some);
some = new SomeVO("F","0","0","123","123","Non trend","AuditA");
myList.add(some);
some = new SomeVO("G","0","0","123","123","Trend","AuditB");
myList.add(some);
Here is my comparator
public String currentAudit = "AuditX";
public class AuditComparator implements Comparator<SomeVO> {
#Override
public int compare(SomeVO o1, SomeVO o2) {
if(currentAudit.equalsIgnoreCase(o1.getAuditType()) && currentAudit.equalsIgnoreCase(o2.getAuditType())) {
int value1 = o2.getUsageCount().compareTo(o1.getUsageCount());
if (value1 == 0) {
int value2 = o1.getNumberofReturns().compareTo(o2.getNumberofReturns());
if(o1.getTrendType().equalsIgnoreCase("Trend") && o2.getTrendType().equalsIgnoreCase("Trend")) {
if (value2 == 0) {
return o1.getTrendNumber().compareTo(o2.getTrendNumber());
} else {
return value2;
}
} else {
if (value2 == 0) {
return o1.getNonTrendNumber().compareTo(o2.getNonTrendNumber());
} else {
return value2;
}
}
}
return value1;
} else {
return 1;
}
}
}
I am trying to sort the VO based on below conditions
First only set of values of currentAudit should be taken in to
consideration i.e., AuditX
a) then it should be sorted with
Usage count in descending order
b) if same usage count found then it
should be sorted with Return count in ascending order
c) if same
return count then it should check for trendType, if trendType
="Trend" then it should sort with Trend number otherwise nonTrend number.
then it should consider rest all auditType's and sorted with
a),b),c) condition as like currentAudit. I tried achieving it and i
ended up with only above comparator. Expected result: D, A, C, E,
F, G. But i get G,F,D,E,B,A,C. Please help me to update the
comparator above.
Your comparator does not meet a simple condition: it is not stateless. A following should always be true: A>B => B<A. In your case, in some scenarios A>B and B>A.
I resolved it by splitting the actual list in to 2 list based on AuditX and rest in another list. Then used below comparator one by one, and then merged in to a result list. Works good.
for(SomeVO some:myList) {
if(some.getAuditType().equalsIgnoreCase("AuditX")) {
auditX.add(some);
} else {
auditY.add(some);
}
}
Collections.sort(auditX, new AuditComparator());
Collections.sort(auditY, new AuditComparator());
public class AuditComparator implements Comparator<SomeVO> {
#Override
public int compare(SomeVO o1, SomeVO o2) {
int value1 = o2.getUsageCount().compareTo(o1.getUsageCount());
if (value1 == 0) {
int value2 = o1.getNumberofReturns().compareTo(o2.getNumberofReturns());
if (value2 == 0) {
return (o1.getTrendType().equalsIgnoreCase("Trend") && o2.getTrendType().equalsIgnoreCase("Trend")) ?
o1.getTrendNumber().compareTo(o2.getTrendNumber()):o1.getNonTrendNumber().compareTo(o2.getNonTrendNumber());
} else {
return value2;
}
}
return value1;
}
The return 1 at the bottom of the comparator makes a bug.
The comparator shall only return 1 if the second element is bigger than the first one, but if they're different, you always return 1, so the very first sorting criteria will be messy.
// a helper for case insensitive comparison
private int compareIgnoreCase(String o1,String o2) {
return o1.toLowercase.compareTo(o2.toLowercase());
}
#Override
public int compare(SomeVO o1, SomeVO o2) {
int result=compareIgnoreCase(o1.getAuditType(),o2.getAuditType());
if (result==0) {
// we need to go to the 2nd criteria
result=o2.getUsageCount().compareTo(o1.getUsageCount());
}
if (result==0) {
// ok, 1st and 2nd criteria was the same, go to the 3rd
result=o1.getNumberofReturns().compareTo(o2.getNumberofReturns());
}
if (result==0) {
// check trends
...
}
return result;
}
I found that this representation of multiple comparison criteria makes the code much easier to follow. We first do the highest priority of comparison, and go on with further comparions if the previous comparisons returned that the two elements are the same (i.e. result is still zero).
In case you need to make a descending sorting at some level, simply put a -, e.g.:
result=-o1.something.compareTo(o2.something)
It is a good idea to have only one exit point in a method (this also makes easier to follow what is happening).
Struggling with a little project I've set myself to learn Java. My goal is to create a program to store a list of Car objects. Then to allow the user to search for a particular car and output all of them if they exist. The car object should contain model name, registration number, vin and colour. Here is what I have so far:
package carObjects;
public class cars {
public static int length;
private String modelName;
private String carColour;
private int regNumber;
private int vin;
public cars(String string, String string2, int i) {
}
public String toString() {
return "Model Name: " + modelName + "Registration Number: " + regNumber
+ "Vin" + vin + "Car Colour: " + carColour;
}
public String getLast() {
return modelName;
}
}
for (int i = 0; i < cars.length; i++) {
cars[i] = new cars("A", "B", 10);
}
for (cars p : cars) {
System.out.println(p.getLast());
}
}
}
Here are some of the things you would need to do:
Since you want to allow searching, you will need to expose accessors to the properties which you would like the user to search for. For instance, if you want to allow users to search by model, you will need to expose the model property. You seem to be doing this through the getLast() method, however, the name is confusing.*
The problem with this code: for (int i = 0; i < cars.length; i++) {
cars[i] = new cars("A", "B", 10);
}
Is that it is creating a series of identical objects. You could use the value of i to provide some dummy, changing values. This will allow you to test that your search is indeed working.
Constructor names should start with an upper case, just like class names.
cars(String string, String string2, int i): Please provide meaningful names to your variables. This will make your code easier to read.
You will need to assign the variables you are getting through your constructor. As is, at the moment your fields will not be initialized to what you are providing.
To create a 2D array, you will need to use the following syntax: Car[][] carArr = new Car[5][5]. This will create a 5x5 array of type car. To iterate over it, you will need to use a nested loop:
for(int i = 0; i < carrArr.length; i++) {
for (int j = 0; j < carrArr[i].lenght;j++) {
...
}
}
* The usage of getters and setters allow you to control which object properties are exposed and how can users interact with them.
The best would be to separate your exercise in two different classes:
class Car {
private String modelName;
private String carColour;
private int regNumber;
private int vin;
public int getVin() {
return vin;
}
public void setVin(int vin) {
this.vin = vin;
}
// other getter/setter
#Override
public String toString() {
return "Car: " + getVin();
}
#Override
public int hashCode() {
return vin;
}
#Override
public boolean equals(Object obj) {
return (obj != null)
&& (obj instanceof Car)
&& ((Car) obj).getVin() == this.getVin();
}
}
CarSet class has the searching methods:
class CarList extends HashSet<Car> {
public Car serarchByVin(int vin) {
List<Car> list = new ArrayList<>(this);
for (Car c : list) {
if (c.getVin() == vin) {
return c;
}
}
return null;
}
public CarSet searchByModel(String model) {
CarSet result = new CarSet();
List<Car> list = new ArrayList<>(this);
for (Car c : list) {
if (c.getModelName()== model) {
result.add(c);
}
}
return result;
}
#Override
public String toString() {
String result = "carList: ";
for (Car c : this) {
result += c;
}
return result;
}
}
I have two array lists that store instances of a class called Book. I am trying to get the book/books that is inside both lists.
This is a search feature that allows you to search for a book by entering the book's ISBN, Name and Author. The list 'resultA' contains the books with the inputted ISBN and Name while the other list 'resultB' contains the books written by the inputted author. To get the final result I need to get the book that is inside both arrays.
I have tried using the retainAll() function but I found that it doesn't work on lists with instances stored.
List<Book> resultA = BookManager.getBooksWhere("book_ISBN", ISBN, "book_name", bookName);
List<Book> resultB = BookManager.getBooksByAuthors(authors);
resultB.retainAll(resultA);
searchResults = resultA;
Is there some other function I can use instead to get the common book?
(Update)
Sorry, Here is the Book class:
public class Book
{
private int bookID;
private String bookISBN;
private String category;
private int libId;
private String name;
#Override
public String toString()
{
String output = bookISBN + " - " + name + " - " + category + " - ";
return output;
}
public int getBookID()
{
return bookID;
}
public void setBookID(int bookID)
{
this.bookID = bookID;
}
public String getBookISBN()
{
return bookISBN;
}
public void setBookISBN(String bookISBN)
{
this.bookISBN = bookISBN;
}
public int getLibId()
{
return libId;
}
public void setLibId(int libId)
{
this.libId = libId;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
(Update)
I did not know that I had to override the Books class for this to work and thanks for pointing that out DNA and pbabcdefp. I have looked up on how to do it and it has worked correctly, the common book is being taken out from both lists.
This was inserted in the book class and uses their unique id to compare if books are equal.
#Override
public boolean equals(Object o)
{
if (o == null)
return false;
if (getClass() != o.getClass())
return false;
final Book otherBook = (Book) o;
if (this.bookId != otherBook.bookId)
{
return false;
}
return true;
}
Assuming you defined an equals function for the Book class, here is a function that can get the common elements in two arrays:
public static <T> List<T> getCommonElements(List<T> list1, List<T> list2) {
List<T> resultsList = new ArrayList<>();
for (T element1: list1) {
for (T element2: list2) {
if (element1.equals(element2)) {
resultsList.add(element2);
}
}
}
return resultsList;
}
This looks like a school question. With that, I doubt you are looking for an answer with generics or comparators or overriding the compareTo or equal method.
Hence, this is what you can do:
for(int x=0; x<listA.size(); x++)
for(int y=0; y<listB.size(); y++)
if(listA.get(x).getISBN().equals(listB.get(y).getISBN()))
return listA.get(x);
Instead of using equals to compare, you get use their ISBN which is supposed to be their unique id. Alternatively, you can override the equals method within the Book class to compare the ISBN.
I have these enums :
public interface MyEnum {
}
public enum Foo implements MyEnum{
A("Foo_a"),
B("Foo_b"),
C("Foo_c")
private String name = "";
Foo(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
public enum Bar implements MyEnum {
A("Bar_a"),
B("Bar_b"),
C("Bar_c")
private String name = "";
Bar(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
I would have to use a method to join my enums like this :
join(Foo, A, B)
or otherwise (and better) :
Foo.join(A, B)
that returns :
"Foo_a, Foo_b"
I tried this :
static String join(MyEnum table, Object ... words) {
String joined = words[0].toString();
for(int i = 1 ; i<words.length ; i++) {
for(MyEnum.class t : MyEnum.values()) {
if (t == words[i]) {
joined += ", " + words[i].toString();
}
}
}
return joined;
}
but it seems I can't do for(MyEnum.class t : MyEnum.values()).
Do you have any idea to implement this method ?
You're not using the parameter table anywhere in your method, you don't need to pass it. Also, why are you trying to loop over the enum values of MyEnum (which doesn't work, since interface MyEnum does not have a values() method)? You can just as well just loop over the words array.
This simple version works with any kind of object, including your enum values:
static String join(Object... words) {
StringBuilder sb = new StringBuilder();
if (words.length > 0) {
sb.append(words[0]);
for (int i = 1; i < words.length; i++) {
sb.append(", ").append(words[i].toString());
}
}
return sb.toString();
}
I really just guess, but I think what you want to do is to join the enums into a single string representation. so from List of enums
[Foo.A, Foo.B, Bar.B]
you want to create string
"Foo_a, Foo_b, Bar_b"
If this is the case, you need to have common method in the interface, which will provide the names:
public interface MyEnum {
String getName();
}
Also your enums must implement this method and return its name in it
public enum Foo implements MyEnum{
#Override
public String getName() {
return name;
}
}
And then you can have your join method:
static String join(MyEnum... words) {
if(words == null || words.length == 0){
return "";
}
StringBuilder joined = new StringBuilder(words[0].getName());
for(int i = 1 ; i<words.length ; i++) {
joined.append(", ").append(words[i].getName());
}
return joined.toString();
}
I have a simple loop that checks for any duplicate results,
where studresults holds my results , result is the object result given to the method and r is the current object from the array.
I have been using this method successfully throughout the program although it is not working in this case even though when I debug result and r , are exactly the same does anyone know why this might be? I have tried #Override already as suggested in other answers to no avail.
I am trying to stop duplicated array elements by throwing an exception.
for(Result r : studresults)
{
if(r.equals(result))
{
return false;
}
}
EDIT OK HERE IS THE WHOLE CLASS>
package ams.model;
import java.util.ArrayList;
import java.util.Arrays;
import ams.model.exception.EnrollmentException;
public abstract class AbstractStudent implements Student {
private int studentId;
private String studentName;
private ArrayList<Course> studcourses = new ArrayList<Course>();
private ArrayList<Result> studresults = new ArrayList<Result>();
public AbstractStudent(int studentId, String studentName) {
this.studentId = studentId;
this.studentName = studentName;
}
public String getFullName() {
return studentName;
}
public int getStudentId() {
return studentId;
}
public Result[] getResults() {
Result[] res = studresults.toArray(new Result[0]);
if(res.length > 0 )
{
return res;
}
return null;
}
public boolean addResult(Result result)
{
for(Result r : studresults)
{
if(r.equals(result))
{
return false;
}
}
studresults.add(result);
return true;
}
public void enrollIntoCourse(Course c)
{
//for re-enrollment
if(studcourses.contains(c))
{
studcourses.remove(c);
studresults.clear();
}
studcourses.add(c);
}
public void withdrawFromCourse(Course c) throws EnrollmentException
{
if(studcourses.size() > 0)
{
studcourses.remove(c);
}
else
throw new EnrollmentException();
}
public Course[] getCurrentEnrolment()
{
return studcourses.toArray(new Course[0]);
}
public abstract int calculateCurrentLoad();
public int calculateCareerPoints() {
// TODO Auto-generated method stub
return 0;
}
public String toString()
{
return studentId + ":" + studentName +":" + calculateCurrentLoad();
}
}
Do you already override hashCode method in Result?
If you override equals, you have to override the hashCode method also to allow you return the same hashcode for the similar objects (objects which has the same value but actually different object instances).
I think the default implementation of hashcode will returns different value for a different object instances even though they have the same values.
Instead I converted toString and then compared and it works???
Makes me think there was something slightly unidentical before?
New method
public boolean addResult(Result r)
{
for (Result s : studresults)
{
String sr1 = s.toString();
String sr2 = r.toString();
if(sr1.equals(sr2))
{
return false;
}
}