I want to create a program to save country code and search the country code. Also, there are at most 20 counters for saving country code. I am a new java beginner. I want to know what is the correct way to write the searchCoutryCode
method by using arrays to search the saved country code before?
public static void createCountryCode(String countryName, String countrycode) {
if (nameCounter >= 20) {
System.out.println("Full");
} else {
System.out.println("Saving the number of " + countryName + ":" + countryCode);
}
countryNameRec[countryNameCounter++] = countryName;
countryCounterRec[countryCounter++]= countryCode;
}
public static void searchCoutryCode(String countryName) {
for(int i = 0; i <=20; i++){
if(countryNameRec[i].equals(countryName)){
System.out.println("countryNameRec[i]+ " : "+ coutryCodeRec[i]");
} else {
System.out.println("No records");
}
}
}
This code assumes country names are unique. In your code you were giving a message about, list size full but adding records anyway. For this kind of problems as recomended by others using maps more suitable.
public static HashMap<String,String> countries = new HashMap<>();
public static void createCountryCode(String countryName, String countrycode) {
if (countries.size() >= 20) {
System.out.println("Full");
} else {
System.out.println("Saving the number of " + countryName + ":" + countrycode);
countries.put(countryName,countrycode);
}
}
public static void searchCoutryCode(String countryName) {
String countryCode = countries.get(countryName);
if(countryCode == null){
System.out.println("No records");
}
else{
System.out.println("countryName+ " : "+ countryCode");
}
}
Iterating in an array to find an element is not an efficient way.
Well, as you have only 20 elements, it will very probably not cause a real issue but whatever you could have more elements to handle later and this way of doing is besides verbose.
Using a binarySearch (Arrays.binarySearch()) with a sorted array or using a Map would be probably better.
Note that actually your searchCoutryCode() doesn't return nothing.
A search method have to return something : the element that it founds or nothing.
You could return String :
public static String searchCoutryCode(String countryName) {
...
}
or better Optional<String> to handle in a cleaner way the not found case :
public static Optional<String> searchCoutryCode(String countryName) {
...
}
I would recommend learning about Maps. They're a smarter version of arrays, and act like dictionaries with "keys" being like the words and "values" being like a definition. Your entire method can be replaced using a call to the containsValue() or containsKey() method from the java library.
However, if you want to use arrays, i would recommend looking into the binary search methods which are part of the Java Arrays library.
Related
This simple method is supposed to add elements to a HashMap. The elements are read from a txt file, I have tested that and everything regarding that area is working just fine. The issue comes when I print the values that are in the Map.Therefore, I think there might be some issue when adding them.
The content of the txt file is
SW: (scores, 90); (scores, 91); (scores, 92);
Where the Permissions is "SW" and the Attributes are "(scores, 90)... (scores, 92)". These are the elements used in the following methods.
public Map<Permissions, ArrayList<Attributes>> paMap;
public void addMap(Permissions per, Attributes att) {
if(paMap.containsKey(per)) {
paMap.get(per).add(att);
}
else{
ArrayList<Attributes> attList = new ArrayList<Attributes>();
attList.add(att);
paMap.put(per, attList);
}
}
//Attributes contain variables (Scores) and values(90-93), that is just for printing
public void printMap() {
ArrayList<Attributes> list;
for(Permissions p: paMap.keySet()) {
list = paMap.get(p);
System.out.print(p.name + ": ");
for(Attributes l: list) {
System.out.print("<" + l.variable +", " + l.value + ">; ");
}
System.out.println();
}
When I print the Map I expect to get exactly the same thing that is in the txt file, but instead I get
SW: (scores, 92); (scores, 92); (scores, 92)
Even if I remove the paMap.get(per).add(att) line from the addMap method I end up getting SW: (scores, 92);
Also, I have tested if the for loop is being called properly and it is.
Therefore, I am confused on how the attributes on the ArrayList are getting updated and what would be the right way of doing it. Do you see any error in the way I am adding or printing the values?
Thank you for your help
I dont know how looks like read method but seems like You are adding all the time the same attribute, so maybe in read function You are not create new attribute but using the same object all the time and just call sets on this, so in the array lsit at the end is the same object added three times
btw:
also method addmap can be replaced by:
paMap.computeIfAbsent(per,x->new ArrayList<Attributes>()).add(att);
If You are using java8 and above ;)
Couple of suggestions:
use interfaces in the Map declaration:
public Map<Permissions, List<Attributes>> paMap;
in order to be used as key in the Map ensure Permissions is
immutable and has equals and hashCode properly defined
So, assuming Permissions has only 1 String field, it should look something like this:
public final class Permissions {
private final String permission;
public Permissions(String permission) {
this.permission = permission;
}
public String getPermission() {
return this.permission;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Permissions that= (Permissions ) o;
return Objects.equals(this.permission, that.permission);
}
#Override
public int hashCode() {
return Objects.hash(this.permission);
}
}
Try another implementation of printMap method. For example, with Java
8:
private void printMap() {
paMap.entrySet().stream().map(this::format).forEach(System.out::println);
}
private String format(Map.Entry<Permissions, List<Attributes>> entry) {
String key = formatPermissions(entry.getKey());
String value = formatAttributes(entry.getValue());
return String.format("%s: %s", key, value);
}
private String formatPermissions(Permissions permissions) {
return permissions.name;
}
private String formatAttributes(List<Attributes> attributes) {
return attributes.stream()
.map(attr -> String.format("(%s, %s)", attr.variable, attr.value))
.collect(Collectors.joining("; "));
}
I am trying to make an erase function to delete the teams of the tournament using the team code (value c in the constructor). Firstly I want to check if that team exists in the objects I made in the main method. Is that possible to do that using an if statement?
Exercise:
Create a java application that stores data for various football teams. Each team has a name, a code and the current points in the championship. In your class create methods for registering new teams, erasing existing teams using their code and showing a list for all the teams currently active in the championship
package assignment.exercise4;
public class Data {
private String name = "";
private int code = 0;
private static int register;
private int erase;
private int currentpoints = 0;
public Data(int c, int points, String n) { //constructor
code = c;
this.currentpoints = points;
name = n;
}
public void Erase(int c)
{
code = c;
if(code != 0)
System.out.println("Team with Code: "+code+" has been erased" );
else
System.out.print("Team with code "+code+" does not exist!");
}
public void Register(String newTeam,int code)
{
name = newTeam;
this.code = code;
System.out.println("New Team " + name + " registered with code " + code);
}
public void print()
{
System.out.println("Team name: " + name + "\nTeam code: " + code + "\nTeam points: " + currentpoints + "\n");
}
}
/*
public static void main(String[] args) {
System.out.println("\nList of Teams: \n");
Data t1 = new Data(110,42,"Juventus");
Data t2= new Data(105,45,"Manchester City");
Data t3= new Data(240,50,"Barcelona");
Data t4= new Data(122,36,"Arsenal");
Data Team = new Data(0,0,""); //use for erase
t1.print();
t2.print();
t3.print();
t4.print();
System.out.println("Teams erased: \n");
Team.Erase(110);
Team.Erase(122);
Team.Erase(0);
System.out.println("\n\nTeams Registered: \n");
t1.Register("Real madrid", 11);
t1.Register("Atletico Madric", 112);
}
}
*/
What are you trying to erase the teams from?
If they were in a list, for example...
Data t1 = new Data(110,42,"Juventus");
Data t2= new Data(105,45,"Manchester City");
Data t3= new Data(240,50,"Barcelona");
Data t4= new Data(122,36,"Arsenal");
List<Data> teams = Arrays.asList(t1, t2, t3, t4);
...you could create a list with a team erased like this...
public List<Data> erase(List<Data> team, int id) {
return team.stream()
.filter(t -> t.getId() != id)
.collect(Collectors.toList());
}
So...
List<Data> remainingTeam = erase(team, 122); // Removes Arsenal
...would remove the first element from the list
I will not answer this to elaborately since it is homework. I will try to give you a hint though.
If you have a team and want to do something with it. Otherwise you just have a team which just stays there in a particular scope (if you do not know what scope is, look it up!). If you have a team you most likely want do do something with it. In this case you seem to want to store information about the teams to use in a championship. Important to note here is that the teams are not the focus here. The real focus is the Championship. The teams are just a part of the championship. There can still be a championship even if all teams does not choose to participate. But you want all teams choosing to participate to be registered to this particular championship (eg UEFA Champions League).
This leads to something called aggregate or association depending on how hard you want to tie the object to the championship. However you do probably not need to pursue these terms any further at this point. What is important to remember is that there is an "has a" relation between the championship and the teams. The championship "has a" collection of participating teams. This is normally reflected in this way in code,
public class Championship {
private Team[] teams; // Or List<Team>, Collection<Team>, HashMap<Team>, ...
}
The Championship can then have methods for registering a team, removing a team, updating status, etc...
public void register(Team t) {
if (numberOfTeams < teams.length) {
teams[numberOfTeams] = t; // Index starts at zero
numberOfTeams++;
} else {
throw new IndexOutOfBoundsException("The list is full. " +
"No more teams may be registered!")
}
}
Even though the function erasing a team was requested, I believe I will not write it down. This design is so different from your original intent, so that writing the erase function will likely solve your complete homework. However, you do actually not have to erase the team it is perfectly possible to just overwrite the position with the next team as,
teams[i] = teams[i+1];
Hope this helps!
Short answer:
public void erase(int id) {
// who needs an if statement, if we can use predicates?
teams.removeIf(team -> team.getId() == id);
}
But this will not work with your current code. Your current code misses the container for your teams.
Longer answer:
For the fun of it. Solving your homework:
class Team {
int id;
String name;
int points;
Team(int id, String name, int points) {
this.id = id;
this.name = name;
this.points = points;
}
#Override
public String toString() {
// ugly formatted... another homework? ;-)
return "Team '" + name + "' (" + id + "): " + points;
}
}
Note, that I will not add any getter or setter, nor will I care about visibility here. I will leave that as another homework for you.
class Championship {
List<Team> teams = new ArrayList<>();
void register(Team team) {
teams.add(team);
}
void erase(int id) {
teams.removeIf(team -> team.id == id);
}
#Override
public String toString() {
// for additional fun... sorted by descending points
return "=== Championship table ===\n"
+ teams.stream()
.sorted((o1, o2) -> Integer.compare(o2.points, o1.points))
.map(Objects::toString)
.collect(Collectors.joining("\n"));
}
}
Somewhere else:
public static void main(String[] args) {
Championship championship = new Championship();
championship.register(new Team(1, "not the best ones", 3));
championship.register(new Team(2, "The better ones", 7));
championship.register(new Team(3, "The winners", 11));
System.out.println(championship);
championship.erase(3);
System.out.println(championship);
}
Output:
=== Championship table ===
Team 'The winners' (3): 11
Team 'The better ones' (2): 7
Team 'not the best ones' (1): 3
=== Championship table ===
Team 'The better ones' (2): 7
Team 'not the best ones' (1): 3
Too much of information? Just start with something like a championship-class or at least use a collection of Teams (e.g. List<Team>).
By the way... Do not deliver this solution as your homework, except you understand what is going on and you can explain it with your own words. Otherwise you are only betraying yourself.
I'm a total newbie to Java, and until now all I've done was draw some shapes and flags. I'm struggling to understand the code I've been given. I need to access values stored in an ArrayList within another class. I'm not sure I'm making any sense, so here are the two classes Seat and Mandate:
package wtf2;
import java.util.*;
public class Seat {
public int index;
public String place;
public int electorate;
public String mp;
public String party;
public String prev;
public ArrayList<Mandate> results;
public Seat(int index, String place) {
this.place = place.trim();
this.index = index;
this.results = new ArrayList<Mandate>();
}
public void addMandate(Mandate m) {
//First candidate is always the MP
if (mp == null) {
mp = m.candidate;
party = m.party;
}
results.add(m);
}
public String toString() {
return "[" + this.index + "," + this.place + "]";
}
}
class Mandate {
public String candidate;
public String party;
public int vote;
public Mandate(String candidate, String party, int vote) {
this.candidate = candidate;
this.party = party;
this.vote = vote;
}
}
The main class contains code that feeds data from 2 text files into Seat and Mandate. From there I managed to access the date in Seat. Like here:
//Who is the MP for "Edinburgh South"
public static String qA(List<Seat> uk) {
for (Seat s : uk)
if (s.place.startsWith("Edinburgh South"))
return (s.mp);
return "Not found";
}
Now,instead of getting just the mp for Edinburgh South I need to get the vote values, compare them to each other, take the second biggest and display the associate party value.
Would appreciate any help, like how to access data from that Array would help me get started at least.
An element in an ArrayList is accesses by its index.
Seems you can just sort your ArrayList based on the vote values of the objects which are in the list.
For this you may want to look here: Sort ArrayList of custom Objects by property
Of course sorting is maybe too much for your given problem. Alternatively,
you may just iterate through the list and pick the two objects with the highest
votes values as you go.
I have created the following method:
public List<String> listAll() {
List worldCountriesByLocal = new ArrayList();
for (Locale locale : Locale.getAvailableLocales()) {
final String isoCountry = locale.getDisplayCountry();
if (isoCountry.length() > 0) {
worldCountriesByLocal.add(isoCountry);
Collections.sort(worldCountriesByLocal);
}
}
return worldCountriesByLocal;
}
Its pretty simple and it returns a list of world countries in the users locale. I then sort it to get it alphabetic. This all works perfectly (except I seem to occasionally get duplicates of countries!).
Anyway, what I need is to place the US, and UK at the top of the list regardless. The problem I have is that I can't isolate the index or the string that will be returned for the US and UK because that is specific to the locale!
Any ideas would be really appreciated.
Anyway, what I need is to place the US, and UK at the top of the list regardless. The problem I have is that I can't isolate the index or the string that will be returned for the US and UK because that is specific to the locale!
It sounds like you should implement your own Comparator<Locale> to compare two locales with the following steps:
If the locales are the same, return 0
If one locale is the US, make that "win"
If one locale is the UK, make that "win"
Otherwise, use o1.getDisplayCountry().compareTo(o2.getDisplayCountry()) (i.e. delegate to existing behaviour)
(This will put the US before the UK.)
Then call Collections.sort with an instance of your custom comparator.
Do all of this before extracting the country names - then extract them from the sorted list.
You could also use a TreeSet to eliminate duplicates and your own Comparator to bring US and GB up to the start.
You are getting duplicates (which this will eliminate) because there are often more than one locale per country. There is a US(Spanish) as well as a US(English) and there are three Switzerlands (French, German and Italian) for example.
public class AllLocales {
// Which Locales get priority.
private static final Locale[] priorityLocales = {
Locale.US,
Locale.UK
};
private static class MyLocale implements Comparable<MyLocale> {
// My Locale.
private final Locale me;
public MyLocale(Locale me) {
this.me = me;
}
// Convenience
public String getCountry() {
return me.getCountry();
}
#Override
public int compareTo(MyLocale it) {
// No duplicates in the country field.
if (getCountry().equals(it.getCountry())) {
return 0;
}
// Check for priority ones.
for (int i = 0; i < priorityLocales.length; i++) {
Locale priority = priorityLocales[i];
// I am a priority one.
if (getCountry().equals(priority.getCountry())) {
// I come first.
return -1;
}
// It is a priority one.
if (it.getCountry().equals(priority.getCountry())) {
// It comes first.
return 1;
}
}
// Default to straight comparison.
return getCountry().compareTo(it.getCountry());
}
}
public static List<String> listAll() {
Set<MyLocale> byLocale = new TreeSet();
// Gather them all up.
for (Locale locale : Locale.getAvailableLocales()) {
final String isoCountry = locale.getDisplayCountry();
if (isoCountry.length() > 0) {
//System.out.println(locale.getCountry() + ":" + isoCountry + ":" + locale.getDisplayName());
byLocale.add(new MyLocale(locale));
}
}
// Roll them out of the set.
ArrayList<String> list = new ArrayList<>();
for (MyLocale l : byLocale) {
list.add(l.getCountry());
}
return list;
}
public static void main(String[] args) throws InterruptedException {
// Some demo usages.
List<String> locales = listAll();
System.out.println(locales);
}
}
yes, when you do sort, just provide your own comparator
Collections.sort(worldCountriesByLocal, new Comparator() {
#Override
public int compare(String o1, String o2) {
if (o1.equals(TOP_VALUE))
return -1;
if (o2.equals(TOP_VALUE))
return 1;
return o1.compareTo(o2);
}
})
where top value will be value what you want to always on top
I would write my own POJO with a sort token consisting of an integer assigning priority (e.g. 0 for US, 1 for UK, 2 for everyone else), then some delimiter and then the country name. Then I would put the array in a HashMap keyed by that sort ID and the POJO as the val. Then I would sort the keys out of the map and iterate through the sorting and retrieve the plain country name for each sorted key.
E.g.
2.Sweden
2.France
2.Tanzania
0.US
1.UK
sorts
0.US
1.UK
2.France
2.Sweden
2.Tanzania
EDIT: a POJO is needed only if you have more fields other than the country name. If it is just the country name, I would set the sort ID as the hash key and the country name as the val and skip the POJO part.
I need to search an object array for a Name and then print out all info corresponding to that name.
I have
public class AccessFriendlyFile {
private Friendlies[] fr = new Friendlies[100];
private int size = 0;
public AccessFriendlyFile (){
try {
Scanner scFile = new Scanner(new File("Friends.txt"));
String line, name, surname, cell, mail, landline;
while (scFile.hasNext()){
line = scFile.nextLine();
Scanner sc = new Scanner(line).useDelimiter("#");
name = sc.next();
surname = sc.next();
cell = sc.next();
if (sc.hasNext()){
mail = sc.next();
landline= sc.next();
fr[size] = new ExtendFriendlies(name, surname, cell, mail, landline);
}
else {
fr[size]= new Friendlies(name, surname, cell);
}
size++;
sc.close();
}
}catch (FileNotFoundException ex){
System.out.println("File not found");
}
How do I code a method that will search "fr" for a name and print out all corresponding info?
Many Thanks
Jesse
Edit:
Here is my Search method, that is currently not working.
public int Search(String name) {
int loop = 0;
int pos = -1;
boolean found = false;
while (found == false) {
if (fr[loop] == name) {
found = true;
pos = loop;
} else {
loop++;
}
}
return pos;
}
Incomparable types error on the if statement.
In your Friendlies class, have a method called getName() that will return the name of that Friendly. Iterate through the fr until you find the matching name. Once you've found that name, use similar get methods to print out all the information you want for the matching Friendly you just found.
I would suggest that you rename your variables here. The Friendlies class stores, I think, a single contact, a Friend. The list of Friend objects is an array that you might beter name friendList or even friendlies. I would also encourage you to not use size as a counter variable. Size is how many friends you have, and you can iterate through them using i, or friendCounter, or use a for each loop as I demonstrate below,
public Friendlies find(String name) {
for(Friendlies friend : fr) {
if(friend.getName().equalsIgnoreCase(name))
return fiend;
}
return null;
}
//now to print the info you can do this:
Friendlies findJoe = find("Joe");
if(findJoe==null)
System.out.println("You have no friends namd Joe.");
else
System.out.println(findJoe);
My code assumes that you implement toString() in Friendlies. If you use netbeans, you can auto-generate this code and then tweak it to get the format you want. (Just right-click where you want to write the method and choose insert code)
This should work:
public List<Friendlies> search(String name) {
List<Friendlies> list = new ArrayList<Friendlies>();
for(Friendlies friendlies : fr) {
if(friendlies.getName().equals(name)) {
list.add(friendlies);
}
}
return list;
}
Then, with the returned list, implement a nice display of the data :)
Assuming the AccessFriendlyFile loads the data into your array, you can use a for each loop, if you want to retieve all the matching names :
List<Friendlies> getByName(String searched){
List<Friendlies> result = new Arraylist<Friendlies>();
for (Friendlies currentFriendly : fr){
if (searched.equalsIgnoreCase(currentFriendly.getName()){
result.add(currentFriendly);
}
}
return result;
}
for only the first one :
Friendlies getByName(String searched){
for (Friendlies currentFriendly : fr){
if (searched.equalsIgnoreCase(currentFriendly.getName()){
return currentFriendly;
}
}
return null;
}
You should use lists instead of fixed arrays. If the files contains more than 100 records you'll get an indexoutofbounds exception.