Been looking for an answer to this but it seems like my problem is more specific than others.
So i have two classes and one interface. The interface is called "Comparable" and i know that the interface does have its own method, but we will get to that in a sec.
What i have is the classes called "cityMain", "City2" and the interface "Comparable"
What my program is doing right now is that it reads from a txt file with something like:
75242;Uppsala
90325;Umeå
96133;Boden
23642;Höllviken
35243;Växjö
51000;Jönköping
72211;Västerås
etc
The semicolon gets away and the integers and strings split into two.
The numbers are zip codes and well the thing next to it is just a name of some states in sweden. After reading it from the "mainCity" i am actually sorting it so that the top zip with it's name gets to be at the top, so from the least number to the largest.
Then when it gets to read it, it goes to the "City2" class and from there it just goes by every method, one zip and one state at the time.
HOWEVER: Atm i am actually calling everything from my main and NOT from my interface.
It should go like this "mainCity" --> "Comparable" --> "City2".
The program works as it is but i want it to be correct!
I have tried to go from the "Comparable" and then call it like that but it didn't work nor did it give me an error.
Note, again: That Comparable does has its own method but i have not used it due to the fact that i wouldn't know of how to apply it as it looks right now.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
public class cityMain {
private static BufferedReader r;
public static void main(String[] args) {
int Z = 0;
String C = null;
try {
ArrayList<City2> City = new ArrayList<City2>();
FileReader file = new FileReader("C:\\Users\\me\\Desktop\\BB.dat");
r = new BufferedReader(file);
String currLine;
while ((currLine = r.readLine()) != null) {
if (currLine.trim().length() > 0) {
String[] split = currLine.split(";");
Z = (Integer.parseInt(split[0]));
C = (split[1]);
City.add(new City2(Z, C));
}
}
Collections.sort(City, (c1, c2) -> c1.getZipCode() - c2.getZipCode());
for (int i = 0; i < City.size(); i++) {
System.out.println(City.get(i).getZipCode() + " " + City.get(i).getCityName());
}
} catch (IOException e) {
System.out.println("Erorr : " + e);
}
}
}
HERE IS A DIFFERENT CLASS:
public class City2 implements Comparable {
private int zipCode;
private String cityName;
public City2(int zipCode, String cityName) {
this.zipCode = zipCode;
this.cityName = cityName;
}
public int getZipCode() {
return zipCode;
}
public String getCityName() {
return cityName;
}
public void addAndPrint() {
}
}
HERE IS THE INTERFACE:
public interface Comparable {
public int getZipCode();
public String getCityName();
public void addAndPrint();
}
What i should get, which i already do get but not in the way that i am supposed to do it!
23642 Höllviken
35243 Växjö
51000 Jönköping
72211 Västerås
75242 Uppsala
90325 Umeå
96133 Boden
Anything would be greatly appreciated right now!
If you explicitly require to use the Comparable interface then change your City2 class to :
public class City2 implements Comparable<City2> {
private int zipCode;
private String cityName;
public City2(int zipCode, String cityName) {
this.zipCode = zipCode;
this.cityName = cityName;
}
public int getZipCode() {
return zipCode;
}
public String getCityName() {
return cityName;
}
public void addAndPrint() {
}
#Override
public int compareTo(City2 city) {
return this.getZipCode() - city.getZipCode();
}
}
Observe that :
Here we are implementing the Comparable<City2> rather than the raw
type Comparable
Overriding the compareTo() to compare zip-codes as required.
There is no need for you to explicitly create an interface
Comparable, but instead just implement the one java provides.
If you plan to use Java standard library sorting you need to use standard interfaces. You need either collection elements to implement java.lang.Comparable or a separate java.lang.Comparator object.
It would be best to delete or rename your own version of Comparator, it makes unclear which one is actually used when looking at your code because java.lang classes are imported automatically.
You have already created a java.lang.Comparator with below (c1, c2) lambda:
Collections.sort(City, (c1, c2) -> c1.getZipCode() - c2.getZipCode());
although you could have written it also as:
Collections.sort(City, Comparator.comparingInt(City2::getZipCode));
Or using List.sort:
City.sort(Comparator.comparingInt(City2::getZipCode));
Okay so...
Now it is almost 100% Complete!
But i am getting the same answer over and over again...
Ideas?
It is like the prints repeat but the last lines are actually correct....
Main class:
public class cityMain
private static BufferedReader r;
public static ArrayList<City2> City = new ArrayList<City2>();
public static void main(String[] args) {
int Z = 0;
String C = null;
try {
FileReader file = new FileReader("C:\\Users\\karwa\\Desktop\\BB.dat");
r = new BufferedReader(file);
String currLine;
while ((currLine = r.readLine()) != null) {
City.sort(Comparator.comparing(City2::getZipCode));
if (currLine.trim().length() > 0) {
String[] split = currLine.split(";");
Z = (Integer.parseInt(split[0]));
C = (split[1]);
City2 d = new City2(Z, C);
City.add(d);
d.print();
}
}
} catch (IOException e) {
System.out.println("Erorr : " + e);
}
}
Second class:
class City2 implements Comparable<City2> {
private int zipCode;
private String cityName;
public City2(int zipCode, String cityName) {
this.zipCode = zipCode;
this.cityName = cityName;
}
public int getZipCode() {
return zipCode;
}
public String getCityName() {
return cityName;
}
#Override
public int compareTo(City2 city) {
return this.getZipCode() - city.getZipCode();
}
public void print() {
for (int i = 0; i < cityMain.City.size(); i++) {
System.out.println(cityMain.City.get(i).getZipCode() + " " + cityMain.City.get(i).getCityName());
}
}
}
Related
I have an object, Pet, and one of the functions is to retrieve its name.
public class pet{
private String petName;
private int petAge;
public pet(String name, int age){
petName = name;
petAge = age;
}
public String getName(){
return petName;
}
public int getAge(){
return petAge;
}
}
I then have an ArrayList which holds a collection of pets as shown in the code below:
import java.util.ArrayList;
pet Dog = new pet("Orio", 2);
pet Cat = new pet("Kathy", 4);
pet Lion = new pet("Usumba", 6);
ArrayList<pet> pets = new ArrayList<>();
pets.add(Dog);
pets.add(Cat);
pets.add(Lion;
I was wondering how I could retrieve the index in the ArrayList or the object that has the name I need. So if I wanted to find out how old Usumba was, how would I do this?
Note: This is not my actual piece of code, it's just used so that I can better explain my problem.
Edit 1
So far, I have the following but I was wondering if there was a better or more efficient way
public int getPetAge(String petName){
int petAge= 0;
for (pet currentPet : pets) {
if (currentPet.getName() == petName){
petAge = currentPet.getAge();
break;
}
}
return petAge;
}
You can't use indexOf() for this purpose, unless you abuse the purpose of the equals() method.
Use a for loop over an int variable that iterates from 0 to the length of the List.
Inside the loop, compare the name if the ith element, and if it's equal to you search term, you've found it.
Something like this:
int index = -1;
for (int i = 0; i < pets.length; i++) {
if (pets.get(i).getName().equals(searchName)) {
index = i;
break;
}
}
// index now holds the found index, or -1 if not found
If you just want to find the object, you don't need the index:
pet found = null;
for (pet p : pets) {
if (p.getName().equals(searchName)) {
found = p;
break;
}
}
// found is now something or null if not found
As the others already stated, you cannot use indexOf() for this directly. It would be possible in certain situations (lambdas, rewriting hashCode/equals etc), but that is usually a bad idea because it would abuse another concept.
Here's a few examples of how we can do that in modern Java:
(as the index topic has already been answered quite well, this only handles direct Object return)
package stackoverflow.filterstuff;
import java.util.ArrayList;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
public class FilterStuff {
public static void main(final String[] args) {
final Pet dog = new Pet("Orio", 2); // again, naming conventions: variable names start with lowercase letters
final Pet cat = new Pet("Kathy", 4);
final Pet lion = new Pet("Usumba", 6);
final ArrayList<Pet> pets = new ArrayList<>();
pets.add(dog);
pets.add(cat);
pets.add(lion);
try {
simpleOldLoop(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
try {
simpleLoopWithLambda(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
try {
filterStreams(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
try {
filterStreamsWithLambda(pets);
} catch (final Exception e) {
e.printStackTrace(System.out);
}
}
private static void simpleOldLoop(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.simpleOldLoop()");
System.out.println("Pet named 'Kathy': " + filterPet_simpleOldLoop(pPets, "Kathy"));
System.out.println("Pet named 'Hans': " + filterPet_simpleOldLoop(pPets, "Hans"));
}
private static Pet filterPet_simpleOldLoop(final ArrayList<Pet> pPets, final String pName) {
if (pPets == null) return null;
for (final Pet pet : pPets) {
if (pet == null) continue;
if (Objects.equals(pet.getName(), pName)) return pet;
}
return null;
}
private static void simpleLoopWithLambda(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.simpleLoopWithLambda()");
System.out.println("Pet named 'Kathy': " + filterPet_simpleLoopWithLambda(pPets, (pet) -> Boolean.valueOf(Objects.equals(pet.getName(), "Kathy"))));
System.out.println("Pet named 'Hans': " + filterPet_simpleLoopWithLambda(pPets, (pet) -> Boolean.valueOf(Objects.equals(pet.getName(), "Hans"))));
}
private static Pet filterPet_simpleLoopWithLambda(final ArrayList<Pet> pPets, final Function<Pet, Boolean> pLambda) {
if (pPets == null) return null;
for (final Pet pet : pPets) {
if (pet == null) continue;
final Boolean result = pLambda.apply(pet);
if (result == Boolean.TRUE) return pet;
}
return null;
}
private static void filterStreams(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.filterStreams()");
System.out.println("Pet named 'Kathy': " + filterPet_filterStreams(pPets, "Kathy"));
System.out.println("Pet named 'Hans': " + filterPet_filterStreams(pPets, "Hans"));
}
private static Pet filterPet_filterStreams(final ArrayList<Pet> pPets, final String pName) {
return pPets.stream().filter(p -> Objects.equals(p.getName(), pName)).findAny().get();
}
private static void filterStreamsWithLambda(final ArrayList<Pet> pPets) {
System.out.println("\nFilterStuff.filterStreamsWithLambda()");
System.out.println("Pet named 'Kathy': " + filterPet_filterStreams(pPets, p -> Objects.equals(p.getName(), "Kathy")));
final Predicate<Pet> pdctHans = p -> Objects.equals(p.getName(), "Hans"); // we can also have 'lambda expressions' stored in variables
System.out.println("Pet named 'Hans': " + filterPet_filterStreams(pPets, pdctHans));
}
private static Pet filterPet_filterStreams(final ArrayList<Pet> pPets, final Predicate<Pet> pLambdaPredicate) {
return pPets.stream().filter(pLambdaPredicate).findAny().get();
}
}
Along with your Pet class, extended by toString():
package stackoverflow.filterstuff;
public class Pet { // please stick to naming conventions: classes start with uppercase letters!
private final String petName;
private final int petAge;
public Pet(final String name, final int age) {
petName = name;
petAge = age;
}
public String getName() {
return petName;
}
public int getAge() {
return petAge;
}
#Override public String toString() {
return "Pet [Name=" + petName + ", Age=" + petAge + "]";
}
}
I am having a hard time finding out how to write my toString Method to get the output of each of my bears in my program. I want the output to show "Race - Points - TotalPoints". But can't manage to get it right even though the rest of the code seems to compile.
Do i need to have the toString defined in both classes or what am I missing? I have checked a couple of other questions that are resembling and that seems to be an alternativ? But how is it most effectively implemented?
First off the bear class:
import java.util.ArrayList;
public class Bear {
public static void main(String[] args) {
Bear b = new Bear("Sebastian", 100, "Brownbear");
ArrayList <Bear> bears = new ArrayList<Bear>();
bears.add(b);
}
private String name;
private int points;
private String race;
public Bear(String name, int points, String race) {
this.name = name;
this.points = points;
this.race = race;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRace() {
return race;
}
public void setRace(String race) {
this.race = race;
}
public int getInitialPoints() {
return points;
}
public int getPoints() {
int oldPoints = points;
points /= 2;
return oldPoints;
}
}
Secondly the BearCollection class:
import java.util.ArrayList;
public class BearCollection {
ArrayList <Bear> bears = new ArrayList<Bear>();
int totalPoints = 0;
public void add (Bear b) {
for (Bear inCollection : bears) {
if(b.getName().equals(inCollection.getName())) {
return;
}
}
for (Bear inCollection : bears)
if (b.getRace().equals(inCollection.getRace())) {
for(int i = bears.size(); i > 0; i --) {
if(bears.get(i).getRace().equals(b.getRace())) {
b.getPoints();
i = 0;
}
}
}
totalPoints += b.getInitialPoints();
bears.add(b) ;
}
public String toString(){
return ;
}
As you were told, just override the toString method. For performance use StringBuilder, rather than String concatenation.
import java.util.*;
public class ans{
public static void main(String[] args){
Bears bears = new Bears();
bears.add(new Bear());
bears.add(new Bear());
bears.add(new Bear());
System.out.println(bears);
}
}
class Bear{
public String toString(){
return "I am a bear";
}
}
class Bears{
private ArrayList<Bear> bears = new ArrayList<Bear>();
public void add(Bear bear){
bears.add(bear);
}
public String toString(){
StringBuilder str = new StringBuilder();
if(!bears.isEmpty()){ // If there is no bears, return empty string
str.append(bears.get(0)); // Append the first one
for(int index = 1; index < bears.size(); index++){ // For all others
str.append(" - "); // Append a separator and the bear string
str.append(bears.get(index));
}
}
return str.toString();
}
}
Edit To print A-B-C-D, just associate every item with a separator except one. A(-B)(-C)(-D) or (A-)(B-)(C-)D. You could add easily a beginning and a end mark.
overriding the toString in Bear class would resolve the issue.
If you need to print out the entire collection of Bears, you'd need to give Bear a toString, something like:
return "Bear("+name+","+points+","+race+")";
Then, in the toString of BearCollection, just write a for each loop in the toString to go through and call toString on each bear in the collection, printing them out.
I want to sort ArrayList according to artist's name I have used comparator interface but I'm not able to sort the list. So kindly help me to solve the problem. The track data will be read from a file Trackdump. The file would contain one track data per line in the format TITLE/ARTIST/RATING/BPM
Here is the code:
import java.io.*;
import java.util.*;
public class MusicLibrary {
ArrayList<Track> songList = new ArrayList<Track>();
public static void main(String args[]) {
new MusicLibrary().go();
}
public void go() {
System.out.println("go");
getTracks();
System.out.println("Before Sorting:");
System.out.println(songList);
Collections.sort(songList);
System.out.println("Sorted according to Artist's name:");
System.out.println(songList);
}
void getTracks() {
System.out.println("gt");
File file = new File("TrackDump.txt");
try{
BufferedReader readr = new BufferedReader(new FileReader(file));
String line = null;
System.out.println(readr);
while ((line = readr.readLine()) != null) {
System.out.println(line);
addSong(line);
}
}catch(Exception e){
e.printStackTrace();
}
}
void addSong(String lineToParse) {
String[] tokens = lineToParse.split("/");
Track nextSong = new Track(tokens[0], tokens[1], tokens[2], tokens[3]);
songList.add(nextSong);
System.out.println(songList);
}
}
class Track implements Comparator<Track>
{
String title;
String artist;
String rating;
String bpm;
public int compare(Track o1, Track o2) {
return o1.getArtist().compareTo(o2.getArtist());
}
public Track(String a, String t, String r, String b) {
title = t;
artist = a;
rating = r;
bpm = b;
}
public boolean equals(Object aSong) {
return this.equals(aSong);
}
public String getArtist() {
return artist;
}
public String getBpm() {
return bpm;
}
public String getRating() {
return rating;
}
public String getTitle() {
return title;
}
public String toString() {
return title + "-" + artist;
}
}
Trackdump:
Title1/Artist1/8/320
Title2/Artist2/10/48
T5/A7/10/120
Title4/A7/9/240
T7/Artist5/7/320
Title6/Artist6/3/240
T9/A7/1/550
T6/Artist8/5/120
T1/Artist9/5/290
Song2/A0/5/320
Song5/A8/10/320
Song1/A2/6/290
You have to implement Comparable class to your Track class. Not Comparator. Then override compareTo() method. It would look like this:
public class Track implements Comparable<Track> {
// Variables, constructor, getters, setters ...
#Override
public int compareTo(Track other) {
return this.getArtist().compareTo(other.getArtist());
}
}
Finally sort with Collections.sort();
You need to implement the Comparable interface and then you can use Collections.sort().
class Track implements Comparable<Track> {
String title;
String artist;
String rating;
String bpm;
#Override
public int compare(Track other) {
return this.getArtist().compareTo(other.getArtist());
}
...
In theory it would work too when implementing Comparator but then you have to pass a Track object into Collections.sort() to act as the Comparator. But that is a rather weird way of doing it so better use the solution above.
Collections.sort(songList, new Track(null, null, null, null));
I want to make an array of objects and use it in different functions. I wrote this pseudocode
privat stock[] d;
privat stock example;
public void StockCheck(){
d =new stock[2];
d[0]= new stock("a","test1", 22);
d[1]= new stock("b","test2", 34);
}
#Override
public stock getStock(String name) throws StockCheckNotFoundException{
int i;
System.out.println("ok" + name + d.legth); // error
example = new stock("example","example",2);
return example;
}
In class test I make an instance of getStock and I call the function getStock stock.getStock();
I get a NullPointerExeption when I do d.length. d is null but I don't understand why.
Hmmmm. If that is in any way like your real code, then the problem is that your "constructor" isn't really a constructor, as you've declared it to return void, making it an ordinary method instead. Remove tbat "void" and it may fix the problem!
Perhaps this example of code will do what you need, using three classes
Test - the main test code
Stock - the implied code for Stock from your question
StockCheck - the corrected code from your question.
(Note: you may really want to use an ArrayList inside StockQuote so you can add and delete Stocks.)
Test class
package stackJavaExample;
public class Test {
public static void main(String[] args) {
String[] testNames = {"test1","test2","notThere"};
StockCheck mStockCheck = new StockCheck();
for (int i=0; i<testNames.length; i++) {
Stock result = mStockCheck.getStock(testNames[i]);
if (result == null) {
System.out.println("No stock for name: " + testNames[i]);
} else {
System.out.println("Found stock: " + result.getName() + ", " + result.getSymbol() + ", " + result.getValue());
}
}
}
}
Stock class
package stackJavaExample;
public class Stock {
private String symbol;
private String name;
private double value;
public Stock(String symbol, String name, double value) {
this.symbol = symbol;
this.name = name;
this.value = value;
}
public String getSymbol() { return symbol;}
public String getName() { return name;}
public double getValue() {return value;}
}
StockCheck class
package stackJavaExample;
public class StockCheck {
private Stock[] d;
public StockCheck() {
d = new Stock[2];
d[0] = new Stock("a","test1", 22);
d[1] = new Stock("b","test2", 34);
}
public Stock getStock(String name) {
for (int i=0; i < d.length; i++) {
if (d[i].getName().equalsIgnoreCase(name)) {
return d[i];
}
}
return null;
}
}
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;
}
}