Change LinkedList elements position - java

I'm supposed to complete a class named "substitute" that can change elements of a LinkedList between them. I've been trying to figure this on my own but I'm kinda new to programming and I wasn't able to find the answer, I would be grateful if someone could help me. Thanks in advance.
I'm given this code which I cannot change, only write between the brackets:
import java.util.Iterator;
import java.util.LinkedList;
public class Device implements Iterable<String>{
private static int numDevices=0; //device counter... static atribute
private String name;
private int id;
protected LinkedList<String> words;
public boolean substitute(String word1, String word2) {
//You can't use ListIterator<>
//You must use indexOf()...
//incomplete code that I'm not allowed to change ahead:
int position = this.words.indexOf(word1.toLowerCase());
return true;
}
I'm also supposed to pass this JUnit5 test:
assertTrue(d1.substitute("amigo", "perla")); //returns true because the word amigo exists --> returns true
assertFalse(d1.substitute("amigo", "perla")); //the word amigo does not exist --> returns false
assertTrue(d1.substitute("estamos", "estas"));
assertTrue(d1.substitute("que", null)); //remove the word que
assertTrue(d1.substitute("tal", null)); //remove the word tal

The LinkedList Class in Java has methods that can help you complete this problem. With the index found in the position, you can call the remove() or set() function to help complete your code.
public boolean substitute(String word1, String word2) {
int position = this.words.indexOf(word1.toLowerCase());
if(position == -1) {
return false; // index of -1 means the word wasn't found in the list, return false
}
if(word2 == null) { // remove item if word2 is null as indicated by tests
words.remove(position);
} else {
words.set(position, word2); // set word2 at the position word1 was found at
}
return true;
}

Related

How to get position of element in ArrayList

I used following method to add my data to ArrayList.
ArrayList<Word> wordList = new ArrayList<Word>();
Word word = new Word();
word.set_id(id);
word.setWord(word);
word.setDefinition(definition);
wordList.add(word);
After the add some data, I want find the position of the any id which I want find in ArrayList.
Already I have tried following method to get position by id. But it isn't work.
int position = wordList.indexOf(id);
and
int position = wordList.lastIndexOf(id);
Both codes always generated "position = -1" as a result. How can I do that?
Edited
This is the code of the Word.java class. How can I implement equal method?
public class Word {
private String _id, word, definition, favourite, usage;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
public String getFavourite() {
return favourite;
}
public void setFavourite(String favourite) {
this.favourite = favourite;
}
public String getUsage() {
return usage;
}
public void setUsage(String usage) {
this.usage = usage;
}
}
indexOf is trying to compare Word objects. Your list doesn't contain ids as the elements, so you get -1.
You need to use a loop and search the list.
int id = 3;
int position = -1;
for (int i = 0; i < wordlist.size(); i++) {
if (wordlist.get(i).getId() == id) {
position = i;
// break; // uncomment to get the first instance
}
}
Note: this will search the whole list to find the last index of that id. So if there are duplicates and you only want the first one (or stop the loop as soon as you find what you want) add a break in the if statement.
Implement equals method in the "Word" object. Inside equals method you can apply equals only to id field.
Create a new Word object with that id and pass that object in indexOf. Don't pass the id in the indexOf. Pass the new of existing Word object with the required id.
Then indexOf will return the valid index of this word object.
For searching the object in a list. you need to override equals method in your Word class. otherwise you will get -1. because indexOf internally used equals method to search the element in list.
The class inside your list should implement hascode() and equals() in order to have indexOf() that works.

I'm trying to search an ArrayList of objects for duplicates and if it doesnt exist add the new object

I have a Class called Subject which will store some information like a subject name and a subject code, I'm struggling because what I'm trying to do is make it loop through the list of records in the arraylist and add the new record if it doesn't already exist. Please help, Ive tried searching for an answer on here but haven't seem to be able to find it.
If looping is not the right thing to do please point me in the right direction.
Thanks
//The Class
public class Subject {
private String name;
private String subjectCode;
public Subject(){
}
public Subject(String name, String subjectCode){
this.name = name;
this.subjectCode = subjectCode;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public String getSubjectCode(){
return this.subjectCode;
}
public void setSubjectCode(String subjectCode){
this.subjectCode = subjectCode;
}
//The Main method
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<Subject> subjectList = new ArrayList<>();
//Test records
subjectList.add(new Subject("Java 1", "ITC101"));
subjectList.add(new Subject("Java 2", "ITC201"));
subjectList.add(new Subject("Java 3", "ITC301"));
String newGetName;
String newSubjectCode;
do {
System.out.print("Enter Subject Name: ");
newGetName = input.nextLine();
System.out.print("Enter Subject Code: ");
newSubjectCode = input.nextLine();
for(int i = 0; i < subjectList.size(); i++){
if(!subjectList.get(i).getName().contains(newGetName) && !subjectList.get(i).getSubjectCode().contains(newSubjectCode)){
subjectList.add(new Subject(newGetName, newSubjectCode));
} else {
System.out.println("We have a match ");
}
}
} while(!"0".equals(newGetName));
}
You are declaring a "no match" too soon: you need to walk the whole list before adding a new subject.
Your program tries the first subject, and if ut does not match, it adds a subject, and moves on. Unfortunately, it does not break, so it keeps adding the same subject for each existing one that does not match.
In order to fix this problem make a boolean variable called "found", set it to false before the loop, and search for matches. Once a match is found, set the variable to true, and break.
After the loop check your variable. If it's true, do not add, and say that you found a duplicate. Otherwise, add the new subject.
in your case, you can not check for 'contains' you have to manually check every entry if its the same.
override the equal() function of your Subject:
public boolean equal(Object o){
Subject b = (Subject) o;
return (this.name.equal(b.name) && this.code.equal(b.code));
}
then in your loop:
boolean found = false;
for(Subject s : subjectList){
if(s.equal(newSubject)){
found = true;
break;
}
}
if(!found) //add new entry
If Subject implements equals(), then create the object and call subjectList.contains(subject). Better yet, implement hashCode() too and change the ArrayList to a HashSet (or LinkedHashSet if order is important) for better performance.
Otherwise, search like this (using equals(), not contains(), for string comparison):
boolean found = false;
for (Subject subject : subjectList)
if (subject.getName().equals(newGetName) && subject.getSubjectCode().equals(newSubjectCode)) {
found = true;
break;
}
if (found)
System.out.println("We have a match ");
else
subjectList.add(new Subject(newGetName, newSubjectCode));

Any way to improve this String comparison with Java?

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class NNNTest {
private String SkillNeed="Java;C++;C";
private String SkillHave="SQL:8;Java:9;C++:5;C:9;PHP:5";
public boolean CheckAvailable(){
int flag=0;
int k;
String [] snar=SkillNeed.split(";");
String [] shandlevel=SkillHave.split(";");
for(int i=0;i<snar.length;i++){
for(k=0,flag=0;k<shandlevel.length;k++){
if(shandlevel[k].split(":")[0].equals(snar[i])){
System.out.println(shandlevel[k].split(":")[0]);
flag=1;
}
}
if(flag==0){
break;
}
}
if(flag==1){
System.out.println("YES");
return true;
}
else{
System.out.println("NO");
return false;
}
}
public static void main(String[] args) {
NNNTest n=new NNNTest();
n.CheckAvailable();
}
}
The method check if you have enough skills to acquire the job.
SkillNeed is a String that with form "skill;skill;skill....."
SkillHave is the skills and level you have and with form "skill:level;skill:level;...."
These are the codes that I typed,but I think it's pretty long and boring,do you have any other way to improve the method?Something like skipping the loop or Array or using java given methods.
Simply way with java-8:
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
public class NNNTest {
private static String skillNeed = "Java;C++;C"; //the skills the job need
private static String skillHave = "SQL:8;Java:9;C++:5;C:9;PHP:5"; //skill and level you have
public static boolean checkAvailable() { //if all the job needed skills match the skills you have
return Arrays.stream(skillHave.split(";")).map(s -> s.split(":")[0]).collect(Collectors.toSet()).containsAll(Arrays.asList(skillNeed.split(";")));
}
public static void main(String[] args) {
System.out.println(checkAvailable());
}
}
Edited for explanation:
Collect al skillHave in a Set (without the number).
Check if the Set of skillHave contains all elements of a given collection.
Collect all SkillNeed in another Set and pass it as parameter for previous step.
Another Java 8 Solution..
It basically iterates through all required skills and makes sure, using the allMatch() function, that each skill is contained in the givenSkills-String. Keep in mind, that you have to check for ":" aswell, otherwise "C" would also match "C++". This also makes sure, that it exactly matches the skill, since the skill is either at the beginning, or it is enclosed by ; and :.
public static boolean checkForRequiredSkills(String requiredSkills, String givenSkills)
{
return Arrays.stream(requiredSkills.split(";")).allMatch(skill -> givenSkills.startsWith(skill + ":") || givenSkills.contains(";" + skill + ":"));
}
A similar solution in earlier java versions could be looking like this
public boolean checkAvailable()
{
for (String skill : skillNeed.split(";"))
{
if (!skillNeed.startsWith(skill + ":") && !skillHave.contains(";" + skill + ":"))
return false;
}
return true;
}
Also the preferred idiom, to iterate over an Array or List is using a for-each loop..
for(String str : stringArray)
doSomething(str);

Replace the return statement below with a statement that returns the first word of theWordList

Please give me in any tips with my class.
I want to make a return statement that will return the first word
in my wordList.
import java.util.ArrayList ;
public class WordList {
private ArrayList<String> theWordList = new ArrayList<String>();
public void addWord(String s) {
theWordList.add(s);
}
/* Check point 5: complete the method below */
public String getFirst() {
/* Replace the return statement bel
ow with a statement
* that returns
* the first word of theWordList (the word at index 0).
* Hint: use the ArrayList method "get".
* If there is no first word (theWordList has no words in it),
* "
-
" should be returned.
*/
return "junk";
}
You can make it this way
public String getFirst() {
if(this.theWordList!=null && this.theWordList.size() > 0)
return this.theWordList.get(0);
return "-";
}
Note : I have returned - (hyphen) when there is no first word in the list or the word list is null (which is not going to happen anyway since it is instantiated earlier)
return theWordList.get(0);
Be sure theWordList is not empty anyway
Make your get function as :
public ArrayList<String> getFirst() {
return this.theWordList;
}
And write a main () AS :
public static void main(String args[]){
WordList w=new WordList();
w.addWord("subash");
//Blah
//blahhhhh ....
System.out.println(w.getFirst().get(0));
}

implement binary search with string prefix?

How can I implement binary search to find a string with a particular prefix in generic array (which in this case will be a string[]). I tried compareTo but that wouldn't help because i have to use a string prefix. eg String prefix "Bi" bill, bilards ...etc..
Implement the following method to return all strings in an alphabetically sorted array that start with a given prefix. For instance, given a prefix “bi”, the returned strings are ”Bill Clinton”, ”Bill Gates”, and ”Bill Joy”. Note that all string comparisons should be case INSENSITIVE. The strings in the returned list must be in the order in which they appear in the array. Your implementation must be based on binary search, and must run in worst case O(log n+k) time, where n is the length of the array, and k is the number of matching strings. Assume that the array has no duplicate entries. If there are no matches, you may either return null, or an empty array list.
You may use the following String methods (in addition to any others you may recall):
boolean startsWith(String s)
int compareTo(String s)
int compareToIgnoreCase(String s)
String toLowerCase(String s)
String toUpperCase(String s)
(As for ArrayList, you only need to use the add method to add an item to the end of the array list.)
You may write helper methods (with full implementation) as necessary. You may not call any method that you have not implemented yourself
public static <T extends Comparable<T>> ArrayList prefixMatch(T[] list, String prefix) {
ArrayList<T> result = new ArrayList<T>();
int lo = 0;
int hi = list.length - 1;
while(lo <= hi) {
int mid = (hi + lo) / 2;
list[mid].startsWith(prefix) ? 0 : list[mid].compareTo((T) prefix));
}
return null;
}
You can use default binary search with custom comparator as your base, and then work our range by your self. I think the right algorithm would be:
Perform binary search on given array. Use comparator which checks only for prefix.
As result you'll get index of string which starts with your prefix
Walk to the left to find first string which matches prefix, remember position.
Walk to the right to find first string which matches prefix, remember position.
Copy elements from range start to range end from original array. That will be your desired array of all elements with prefix match condition.
Below is implementation in java. It works in happy case scenario but will crash if(I left those checks out to make code look simple):
No strings with given prefix exist in original array
There are string with length less then prefix length
Also if you need binary search implementation you could check source of Arrays.binarySearch
public class PrefixMatch {
public static void main(String[] args) {
final String[] prefixMathces = prefixMatch(new String[] { "Abc", "Abcd", "Qwerty", "Pre1", "Pre2", "Pre3", "Xyz", "Zzz" }, "pre");
for (int i = 0; i < prefixMathces.length; i++)
System.out.println(prefixMathces[i]);
}
public static String[] prefixMatch(final String[] array, final String prefix) {
final Comparator<String> PREFIX_COMPARATOR = new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o1.substring(0, prefix.length()).compareToIgnoreCase(o2);
}
};
final int randomIndex = Arrays.binarySearch(array, prefix, PREFIX_COMPARATOR);
int rangeStarts = randomIndex, rangeEnds = randomIndex;
while (rangeStarts > -1 && array[rangeStarts].toLowerCase().startsWith(prefix.toLowerCase()))
rangeStarts--;
while (rangeEnds < array.length && array[rangeEnds].toLowerCase().startsWith(prefix.toLowerCase()))
rangeEnds++;
return Arrays.copyOfRange(array, rangeStarts + 1, rangeEnds);
}
}
I assume that you currently have something like this? :
arrayElement.compareTo(prefix)
If so, you can change it to look like this:
arrayElement.startsWith(prefix) ? 0 : arrayElement.compareTo(prefix)
I suggest looking into the API code for this. There is an Arrays class that you can check out in the java.lang package and learn from there.
Working on a similar problem right now. I believe pseudo code will go something like yours. I created a pojo class Song. A song is made up up three strings artist,title, and lyrics.
When you create a song object you get :
// Artist Title Lyrics..
Song a = ["Farmer Brown", "Oh' Mcdonalad", "Oh'mcdonal had a farm eh i oh i oh"]
public class Song implements Comparable<Song> {
private String _artist;
private String _lyrics;
private String _title;
// constructor
public Song(String artist, String title, String lyrics) {
this._artist = artist;
this._title = title;
this._lyrics = lyrics;
}
public String getArtist() {
return _artist;
}
public String getLyrics() {
return _lyrics;
}
public String getTitle() {
return _title;
}
public String toString() {
String s = _artist + ", \"" + _title + "\"";
return s;
}
//This compare two song objects
public int compareTo(Song song) {
String currentSong = song.toString();
int x = currentSong.compareToIgnoreCase(this.toString());
return x;
}
This is your method here that will take in the array of songs and your prefix and use the compare method to see if they match. If they match the compareTo method returns a 0. If you get a 0 then you know you have found your song so return the arrayOfSongs[index where song is found].
I have not coded up my search yet but I modified yours to match my code. I have not tested it yet. I don't think you even need a compareTo method but you can use it. Also for scaling the binary search should return a list of songs that might match as you might have multiple songs that start with "xyz" . Kind of when you start searching on google with prefix "do" you get a drop down of "dog, donut,double" which gives the user something to choose like a search engine.
public static ArrayList<Song> search (String[] arrayOfSongs , String enteredPrefix) {
ArrayList<Song> listOfMatches = new ArrayList<Song>;
int mid;
int lo = 0;
int hi = arrayOfSongs.length - 1;
while(lo <= hi)
{
mid = (hi + lo) / 2;
if(arrayOfSongs[mid].startsWith(enteredPrefix))
{
System.out.println("Found a match, adding to list");
listOfMatches.add(arrayOfSongs[mid]);
}
}
return listOfMatches;
}
Once you have a listOfMatches of possible suspects of the song you want you can use the compareTo method in some way.

Categories