I have to add a String parameter to the end of an array. And throw an exception if the String already exists in the array. I don't know. Can anyone help?
This is what I have so far
public static void addCity (String city) throws Exception
{
for (int i = 0; i < MAX_CITIES;i++)
{
if (city == cityNames[i])
throw new Exception("This city already exists");
}
String [] temp = new String[cityNames.length+1];
for (int i = 0; i < cityNames.length;i++) {
temp[i] = cityNames[i];
}
temp[temp.length-1] = city;
cityNames = temp;
manyItems++;
}
To test if String a equals String b, use a.equals(b), not a == b.
(a == b works in C++, not Java.)
Your code looks fine except for the String comparison:
if (city == cityNames[i])
This won't do a proper String comparison: it will only compare the object references, which will usually be false.
Use String.equals for this:
if (city.equals(cityNames[i]))
It'd be easier to use a List:
List<String> cityNames = new ArrayList<String>();
if(cityNames.contains(city)) {
throw new Exception("This city already exists");
}
cityNames.add(city);
What is MAX_CITIES? I think your first loop should be until i < cityNames.length, not MAX_CITIES, since you don't seem to be updating MAX_CITIES when you increase the size of the array.
You should be using the equals() method to compare String objects, rather than ==.
It also might be nice if instead of just making the new array one element bigger, you double the size. That way you don't have to go through all the work of copying the array every time you add a new element. You'd need a variable to keep track of the next empty spot in the array, and it would look something like this:
if (nextEmptyIndex == cityNames.length)
{
String [] temp = new String[cityNames.length*2];
for (int i = 0; i < cityNames.length;i++) {
temp[i] = cityNames[i];
}
}
temp[nextEmptyIndex] = city;
nextEmptyIndex++;
manyItems++;
Related
I'm creating a java scraping program using selenium and inserting the data into a database. I'm actively looking to improve my skillset but I don't find instructional videos too helpful since I lose interest, but I really enjoy learning through doing. This code below works as needed, but it looks really really ugly and I feel there must be a better/cleaner solution. For reference it builds a comma separated string with data such as "Value1", or "Value1, Value2", etc depending on the keyword count. My original logic was outputting ", Value1, Value2" which is why I added the "if (x ==0)" logic. I have a lot of methods that are just sloppy like this, so any pointers for improving my code is appreciated, thanks!
ArrayList<String> keywords = new ArrayList<String>();
keywords = keywordChecker(title);
for (int x = 0; x < keywords.size(); x++) {
String list = keywords.get(x);
if (x == 0) {
keywordListBuilder = list;
} else if (x > 0) {
keywordListBuilder = keywordListBuilder + ", " + list;
}
}
keywordValues.add(keywordListBuilder);
public ArrayList<String> keywordChecker(String title) {
ArrayList<String> keywordList = new ArrayList<String>();
String keyword1 = "";
String keyword2 = "";
String keyword3 = "";
String[] keywordTextCombinations = { "Value1", "Value2", "Value3", [imagine a list of 20 items]};
for (int i = 0; i < keywordTextCombinations.length; i++) {
if (title.toLowerCase().contains(keywordTextCombinations[i].toLowerCase())) {
keyword1 = keywordTextCombinations[i];
keywordList.add(keyword1);
break;
}
}
for (int i = 0; i < keywordTextCombinations.length; i++) {
if (title.toLowerCase().contains(keywordTextCombinations[i].toLowerCase())
&& !keywordTextCombinations[i].toLowerCase().equals(keyword1.toLowerCase())
&& !keywordTextCombinations[i].toLowerCase().equals(keyword2.toLowerCase())) {
keyword2 = keywordTextCombinations[i];
keywordList.add(keyword2);
break;
}
}
for (int i = 0; i < keywordTextCombinations.length; i++) {
if (title.toLowerCase().contains(keywordTextCombinations[i].toLowerCase())
&& !keywordTextCombinations[i].toLowerCase().equals(keyword1.toLowerCase())
&& !keywordTextCombinations[i].toLowerCase().equals(keyword2.toLowerCase())) {
keyword3 = keywordTextCombinations[i];
keywordList.add(keyword3);
break;
}
}
return keywordList;
}
ArrayList<String> keywords = new ArrayList<String>();
keywords = keywordChecker(title);
This will:
Create a new variable, named keywords, that can point at arraylists.
Makes a new arraylist object.
Assigns the reference to this newly created object to the keywords variable.
Then tosses that reference away and makes that created object instant garbage, as you then immediately assign some other reference to it.
In other words, that new ArrayList<String>(); does nothing whatsoever but waste time and space. Get rid of it. Let's also be like other java coders and use the most general type that we're interested in. For beginners, that basically means, 'the variable should be of type List, not ArrayList. It's good to write code in similar style to other java coders; makes it easier to read their code and it makes it easier for them to read your code.
List<String> keywords = keywordChecker(title);
for (int x = 0; x < keywords.size(); x++) {
String list = keywords.get(x);
if (x == 0) {
keywordListBuilder = list;
} else if (x > 0) {
keywordListBuilder = keywordListBuilder + ", " + list;
}
}
keywordValues.add(keywordListBuilder);
You're getting a single keyword and you call this list? Names are important. When they lie, your code becomes unreadable.
You're turning a list of strings into a single string with all the values, separated by a comma. That sounds like a common job. When something sounds common enough, search the web. You'll usually find that there's a one-liner. So it is here:
keywordValues.add(String.join(", ", keywords));
Oof, that's way less code.
The keywordChecker method
It helps to document code, especially when asking for help. Evidently, this method is to scan the provided title variable, and search for any of a list of keywords, then it is to return each matching keyword. However, you've limited to return at most 3. I assume you didn't want that. But if you do, I'll show you how, with a one-liner of course.
String keyword1 = "";
String keyword2 = "";
String keyword3 = "";
When you start naming variables like this, stop. There's no way that's correct. Think for a moment. You're already using them, you know how to do this properly: Lists. Once you use a list, this becomes near trivial. Also, method names should generally be a verb; common java style. Let's also make constants, well, constant. Let's also avoid arrays, they are unwieldy and annoying.
private static final List<String> KEYWORDS = List.of("Value1", "Value2", "Value3", [imagine a list of 20 items]);
public List<String> findMatchingKeywords(String title) {
var out = new ArrayList<String>();
String lowercased = title.toLowerCase();
for (String keyword : KEYWORDS) {
if (lowercased.contains(keyword.toLowerCase()) out.add(keyword);
}
return out;
}
That eliminated a ton of lines, that's nice. If you want to return no more than 3 keywords at most... all you need to do is abort looping when you're 'full'. As last line within the for loop:
if (out.length() == 3) break;
Putting it all together:
keywordValues.add(String.join(", ", findMatchingKeywords(title)));
...
private static final List<String> KEYWORDS = List.of("Value1", "Value2", "Value3", [imagine a list of 20 items]);
public List<String> findMatchingKeywords(String title) {
var out = new ArrayList<String>();
String lowercased = title.toLowerCase();
for (String keyword : KEYWORDS) {
if (lowercased.contains(keyword.toLowerCase()) {
out.add(keyword);
if (out.length() == 3) break;
}
}
return out;
}
You can try to do everything in one for loop. Also, I recommend that you use a HashSet since you are comparing elements. A HashSet cannot contain duplicate elements, so if you try to add an element that already exists it doesn't do it and it returns false (Yes, the add function in HashSet returns a boolean).
I'm trying to answer this question:
Program the method findIngredients. This method takes in a String called
foodInStock, and an ArrayList of Strings called ingredients. The method should return an
ArrayList of ingredients that were not found in foodInStock.
for example if:
foodInStock = “tomatopotatocornturkeycarrotstuffing”
ingredients = {“potato”, “corn”, “salt”, “chicken”, “turkey”}
returns {“salt”, “chicken”}
I tried writing some code but for some reason everything is getting removed when I use the above example on my program. Where did my program go wrong?
Here's my code:
public static ArrayList<String> findIngredients(String foodInStock, ArrayList<String> ingredients){
ArrayList<String> ingredientsNotFound = new ArrayList<String>();
int i = 0;
for (; i < ingredients.size(); i++) {
for (int x = 0; x < foodInStock.length()-(ingredients.get(i).length())+1; x++) {
if (ingredients.get(i) == foodInStock.substring(x, (x + ingredients.get(i).length()))) {
ingredients.remove(i);
i = 0;
break;
}
}
}
ingredients = ingredientsNotFound;
return ingredientsNotFound;
}
I think there are two main things to cover here.
First, the way to build the final result. You are currently removing items from the original input; a better strategy is to add items to a new list (partially because it's simpler to think about and partially because you generally don't want to modify a list while iterating over it).
You also are, probably accidentally, overwriting your list with an empty list at the end.
Second, the way to determine whether or not the ingredient is in the string input. Rather than looping over the whole string and inspecting substrings, you can instead use the indexOf() method to see whether or not the string includes the current item.
public static ArrayList<String> findIngredients(String foodInStock, ArrayList<String> ingredients) {
ArrayList<String> results = new ArrayList<>();
for (String ingredient : ingredients) {
if (foodInStock.indexOf(ingredient) == -1) {
results.add(ingredient);
}
}
return results;
}
Here we initialize a new list for the results. We then loop over every individual ingredient in the input list, and ask whether or not that ingredient is present in the string input. When it is not (indexOf() returns -1), we add it to the results list. At the end, the results contains every ingredient not found.
Suppose I have an array which contains the values
String studentList[] = {Paul, null, null};
Now I wanna add another student but make sure before if the student is not already in there.
I have already a for loop which checks if the value is null and if it is then add the student.
You should use a Set, HashSet as the exact implementation and convert that to array afterwards.
Add result to a hash set
1.HashSet contains unique elements only.
HashSet<String> studentList=new HashSet<String>();
studentList.add("Paul");
You'd be better off using a Set, however, you can do this:
String studentList[] = {"Paul", null, null};
for (int i = 0; i < studentList.length; ++i) {
if (studentList[i] == null) {
studentList[i] = newStudent;
break;
} else if (studentList[i].equals(newStudent)) {
break;
}
}
This method removes duplicate objects from a list that have the same address field. it works for me at the moment. But I am upgrading my application and I am expecting my ArrayLists to get bigger. (200+ objects)
I am worried it might be too slow for comparing 200 records for example, since It is O(n2)
How can I improve it.
public static ArrayList<Place> removeDuplicates(ArrayList<Place> masterList) {
ArrayList<Place> tempList = new ArrayList<Place>(masterList);
for (int i = 0; i < tempList.size(); i++) {
String address = tempList.get(i).getAddress();
for (int j = 0; j < tempList.size(); j++) {
String address2 = tempList.get(j).getAddress();
if (address.equalsIgnoreCase(address2) && i != j) {
tempList.remove(tempList.get(j));
}
}
}
return tempList;
}
edit
Thanks all for the unanimous answers. I have a finasl question. What goes in the hashcode and equals methods when I over ride them?
Make sure the instances produce a good hashcode and use HashSet or LinkedHashSet (if you want to preserve order):
return new ArrayList<Place>(new LinkedHashSet<Place>(masterList));
The best you can do is overwriting the hashcode and equals methods and generate a Set from your list.
In this way is java that takse care of removing duplicate elements in the list, and not you.
public static ArrayList<Place> removeDuplicates(ArrayList<Place> masterList) {
Set<Place> temp = new HashSet<Place>();
for(Place place : masterList) {
if(!temp.add(place)) {
masterList.remove(place);
}
}
return masterList;
}
Your masterlist of places
List<Place> masterList = new ArrayList<Place>();
masterList.add(new Place());
masterList.add(new Place());
masterList.add(new Place());
Removing the duplicates by adding to set "s"
Set<Place> s = new TreeSet<Place>(new Comparator<Place>() {
#Override
public int compare(Place o1, Place o2) {
return o1.getAddress().compareToIgnoreCase(o2.getAddress());
}
});
s.addAll(masterList);
Printing your result
List<Object> res = Arrays.asList(s.toArray());
for (Object object : res) {
Place place = (Place)object;
}
If you have equals and hashcode defined for Place object, just create HashSet from arraylist, and then create arraylist from set.
I have a two dimensional array that contains pairs of strings. If one string is found it should replace it with its pair.
The code:
for (int i = 0; i < pairs.length; i++) {
if (name.contains(pairs[i][0])) {
name.replaceAll(pairs[i][0], abbr[i][1]);
}
}
It is not replacing the strings. What is the error?
You are neglecting to assign the result of replaceAll, and so the modification is lost.
Perhaps you want to keep the modified string as name:
for (int i = 0; i < pairs.length; i++) {
if (name.contains(pairs[i][0])) {
name = name.replaceAll(pairs[i][0], abbr[i][1]);
}
}
Note that java String objects are immutable, so calling name.replaceAll doesn't modify name, it returns a new String with the modifications.
String is immutable.
name.replaceAll(pairs[i][0], abbr[i][1]);
creates a new String (it doesn't modify the "name" String)
Try
name = name.replaceAll(pairs[i][0], abbr[i][1]);
A modified version of the string is being created, however it's return value is being lost.
name = name.replaceAll(pairs[i][0], abbr[i][1]);
should work.