I build removing duplicates, however I'm thinking how to use a method that removes the duplicate elements from an array list of integers using the following header:
public static void removeDuplicate(ArrayList<Integer> list)
write a test program that prompts the user to enter 10 integers to a list and
displays the distinct integers separated by exactly one space.
import java.util.ArrayList;
import java.util.Scanner;
public class RemoveDuplicates {
public static void main(String[] args){
ArrayList<Integer>list = new ArrayList<Integer>();
Scanner input = new Scanner (System.in);
System.out.print("Enter integers (input ends with 0): ");
int value;
do{
value = input.nextInt();
if(!list.contains(value)&& value !=0)
list.add(value);
}while (value !=0);
input.close();
for (int i = 0; i < list. size(); i++)
System.out.print(list.get(i) + " ");
}
}
It's my code,please modifying please, how to use method and test .
If I understand correctly, you should implement a method with this header
public static void removeDuplicate(ArrayList<Integer> list)
judging by its name, I'd say that method should remove the duplicates from the list and not (as you are doing it right now) the do-while-loop during input.
So first remove the check in your loop (if(!list.contains(value)&& value !=0)) and just add every number the user types to the list.
Then you can make a call to the method removeDuplicate(list);. If you want you can add this call in your loop and it will be executed after every input or you execute it just once when the input is closed.
Now implementing the method:
public static void removeDuplicate(ArrayList<Integer> list) { // this is the header you need to use
The problem here is, the method knows the list but not the element that is a possible duplicate. So you have to look for it
for (int i = 0; i < list.size(); i++) { // iterate through every element in the list
Integer current = list.get(i); // for convenience, save the current list item in a variable
So, you check every integer in the list – one by one.. but if you want to know if the integer exists a second time, you have to search the tail of the list. Meaning you have to check the sublist after i.
List sublist = list.subList(i + 1, list.size()); // the sublist with all elements of the list from i+1 to the end
your list.contains(value) line is correct, you can use it here as well. Only now you call it on the sublist
if(sublist.contains(current)){ // checks if the number is in the sublist
sublist.remove(current); // removes the number from the sublist
}
This however would only remove the first duplicate. Alternatively, you can remove every item in the list that equals the current integer:
while (sublist.contains(current)) {
sublist.remove(current);
}
And that's it. Your method is finished.
}
}
It is finished because you are actually working on the one and only list in your program. Even when you remove an integer from your sublist, it is actually removed from the sublist and the real list (the sublist is just a reference, and not an actual list on its own)
EDIT
for your convenience here the complete code with both methods. If you compare the code to yours, you'll see that there is not much different:
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
System.out.print("Enter integers (input ends with 0): ");
int value;
do {
value = input.nextInt();
if (value != 0) { // this changed: add every number except 0
list.add(value);
}
} while (value != 0);
input.close();
removeDuplicate(list); // here you make the call for the new method
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
}
// and this is the new method
public static void removeDuplicate(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
Integer current = list.get(i);
List sublist = list.subList(i + 1, list.size());
while (sublist.contains(current)) {
sublist.remove(current);
}
}
}
If you don't want duplicate, use a collection that implements the Set interface (http://docs.oracle.com/javase/7/docs/api/java/util/Set.html) instead of an array list.
Related
I am trying to write a program where the user can write their grocery item list, and then they can search whether they have wrote that item on the list or not. When they find if they have wrote down the item name it's suppose to return the index number and if they haven't wrote down the item name it's suppose to return -1. So far my code is able to find out if they have wrote down the item or not in Boolean expression.
import java.util.Scanner;
import java.util.Arrays;
public class GroceryStoreTest {
// for the search item we need to create a method.
I wrote down a boolean method for the search item.
public static boolean contains(String [] arr, String targetItem){
for(String find : arr){
if(targetItem.equals(find))
return true;
} return false ;
}
public static void main(String[] args) {
//lets create an array of string and add items list
int list;
Scanner input = new Scanner(System.in);
System.out.print("How many items would you like to add to the list: ");
list = input.nextInt();
String[] items = new String[list];
System.out.print("Write down the name of item without any space.\n(i.e.; Green Paper = GreenPaper)\n\nItems list: \n");
int i;
for (i = 0; i < list; i++) {
System.out.printf((i+1 ) + ".");
items[i] = input.next();// asks for next item name
}
// search in the items list
String search = " ";
System.out.print("Enter the name of the item to check if you have listed: " + search);
search = input.next();
//System.out.print(contains(items, String.valueOf(input)));
System.out.print(contains(items, search));
input.close();// it will stop taking the input
}
}
The other answers are correct, but there is another perspective: you should understand the difference between the for-each and the "counting-for" loops.
You got:
public static boolean contains(String [] arr, String targetItem){
for(String find : arr){
if(targetItem.equals(find))
return true;
}
return false ;
}
Which is already pretty good. ( Maybe expect for the subtle thing that I would advise you to always put blocks in { braces }; as it is far too easy to get things wrong in order to save that little bit of typing. )
But in general, that code is OK. One should actually prefer this style of looping. Because that construct really improves readability by making you "read less".
But in your case: you need that index. So the for-each loop doesn't give you what you need. Thus - this is a case where an old school counter loop is better:
for (int i=0; i<arr.length;i++) {
... and now i is the index you are looking for; thus the value to return
or -1 in the end if nothing matched
Why not just change your contains method to return an int instead?
public static int indexOf(String [] arr, String targetItem){
for(int i = 0 ; i < arr.length ; i++) {
if(targetItem.equals(arr[i]))
return i;
}
return -1 ;
}
Alternatively, you don't need to create your own indexOf method, you can just call Arrays.asList(items).indexOf("valueSearch") to get the index.
Another way to do this is to use an array list instead of an array. An ArrayList is basically an array without a fixed length. Your code will look like this:
Scanner input = new Scanner(System.in);
ArrayList<String> items = new ArrayList<>();
System.out.print("Write down the name of item without any space.\n(i.e.; Green Paper = GreenPaper)\n\nWrite "END" to finish entering items\n\nItems list: \n");
while(true) {
String item = input.next();
if (item.equals("END")) {
break;
}
items.add(item);
}
// search in the items list
String search = " ";
System.out.print("Enter the name of the item to check if you have listed: " + search);
search = input.next();
System.out.print(items.indexOf(search));
input.close();// it will stop taking the input
Here is an example of how to remove all occurences of something from an array list:
ArrayList<String> a = new ArrayList<>();
a.add("Hello");
a.add("Hello");
while (a.contains("Hello")) {
a.remove("Hello");
}
through a cycle, comparing the values with the value adding looking toLoweCase method to avoid problems with case sensitive
for(int i = 0 ; i < items.length ; i++) {
if(targetItem.toLowerCase().equals(items[i].toLowerCase()))
System.out.println("Index " + i);
}
or using the ArrayList class can be done as follows
System.out.println(Arrays.asList(items).indexOf("valueSearch"));
I have two different arrays and they both contain the same type of element. The elements are obtained from user input. And the arrays can store fixed size of element.
*Let's say that fisrt one is basically an arrayList and it adds the user input into the list.
The second one is simply an array which also gets value from user input. All the elements of second array are also contained in the first array and the length of this array is less than the first array*
Now I want to print an array which is the result of first array-second array.
This is the program I am working on right now. You may avoid this coding just to give me a theoritical concept for doing that.
package issuetracking;
import java.util.*;
public class IssueTrackingObject {
ArrayList<String> crIss = new ArrayList<String>();
Scanner input = new Scanner(System.in);
boolean crIss_bool;
int numOfSolvedIss;
private String[] solvedIss;
//lets user create some issues and add them into an arrayList
public void createIssue() {
System.out.println("Enter 5 issues: ");
for (int i = 0; i < 5; i++) {
System.out.println("Issue " + (i + 1 + ": "));
crIss_bool = crIss.add(input.nextLine());
}
}
//Let user mark some issues as solved (which are already in the list that the user has just created)
public void solvedIssue() {
System.out.println("How many solved issue you have(Must be less than 5): ");
numOfSolvedIss = input.nextInt();
solvedIss = new String[numOfSolvedIss];
for (int k = 0; k < numOfSolvedIss; k++) {
System.out.print("Enter solved issue(REMEMBER THAT THE SOLVED ISSUE MUST BE FROM ONE OF THEM YOU ALREADY HAVE CREATED)no. " + (k + 1) + ": ");
solvedIss[k] = input.next();
}
}
public void printUnsolvedIssue() {
//print out the elements of createIssue() that doesn't belong to the solvedIssue()
}
You can use a simple solution like this:
for (String solved : solvediss) {
if (solved != null) crIss.remove(solved);
}
This will remove all the Strings from the list that are in the array.
Of course, you could also do this.
crIss.removeAll(Arrays.asList(solvediss));
Go over your second array and use the remove method in arraylist to remove every element of second array from the first.
for (int i = 0; i < solvedIss.length; i++) {
crIss_bool = crIss.remove(solvedIss[i]);
}
Removing the elements might be the simplest method in this case, but it causes original list to change.
If you do not wish to have any destructive modification to the original list, you could perform a simple search like following.
for (String issue : crIss) {
bool isUnSolved = true;
for (String solvedIssue : solvedIss) {
if (issue.equals(solvedIssue)) {
isUnSolved = false;
break;
}
}
if (isUnSolved) {
// Print the 'issue' or do whatever you want to do with it.
}
}
Hope this helps.
Good luck.
I'm writing a method that allows me to count how many times an element of type String shows up in a LinkedList of type Strings. my code shown below does not work. I keep getting index out of bounds in the line i commented on down below. Can't seem to find the bug
public int findDuplicate (LinkedList<String> e) {
int j = 1;
LinkedList<String> test = e;
while (!test.isEmpty()){
test = e;
String value = test.pop();
//Screws up here when i = 6
for(int i =0; i<=test.size() && test.get(i)!=null; i++){
String value3 = test.get(i);
if(e.get(i).equals(value) && i<=test.size()){
String value2 = test.get(i);
j++;
String Duplicate = e.get(i);
e.remove(i);
}
}
System.out.println(value + " is listed " + j + " times");
}
return j;
}
using hashmaps.. still doesn't work
public void findDuplicate (LinkedList e) {
Map<String,Integer> counts = new HashMap<String,Integer>();
while(!e.isEmpty()){
String value = e.pop();
for(int i =0; i<e.size(); i++){
counts.put(value, i);
}
}
System.out.println(counts.toString());
}
My code should go through the linked list find out how many times an element within the list appears and deletes duplicates from the list at the same time. Then prints the element and the number of times it appears in the list. I posted about this last night but didn't get a response yet. Sorry for the repost.
You are running off the end of the list. Change
for(int i =0; i<=test.size() && test.get(i)!=null; i++){
to
for(int i =0; i< test.size() && test.get(i)!=null; i++){
Valid indexes for a List (or an array) are 0 through size() - 1.
Regarding your hashmap example to count the duplicates:
#Test
public void countOccurrences() {
LinkedList<String> strings = new LinkedList<String>(){{
add("Fred");
add("Fred");
add("Joe");
add("Mary");
add("Mary");
add("Mary");
}};
Map<String,Integer> count = count(strings,new HashMap<String,Integer>());
System.out.println("count = " + count);
}
private Map<String, Integer> count(List<String> strings, Map<String, Integer> runningCount) {
if(strings.isEmpty()) {
return runningCount;
}
String current = strings.get(0);
int startingSize = strings.size();
while(strings.contains(current)) {
strings.remove(current);
}
runningCount.put(current, startingSize - strings.size());
return count(strings,runningCount);
}
If you want the original strings list preserved you could do
Map<String,Integer> count = count(new LinkedList<String>(strings),new HashMap<String,Integer>());
System.out.println("strings = " + strings);
System.out.println("count = " + count);
Check out google's guava collections which has a perfect class for maintaining a map and getting a count:
https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap
Multiset<String> wordsMultiset = HashMultiset.create();
wordsMultiset.addAll(words);
// now we can use wordsMultiset.count(String) to find the count of a word
I hope you realize what the test = e statement is doing. After this statement executes both test and e refer to the same object.
If anyone of them modifies the list, the other sees it as they both are looking at the same object.
If this is not intended you need to clone the list before assigning it to another list reference.
This doesn't affect your out of bounds issue, but you are removing elements from your list while still evaluating it. If you remove an element, you should call i-- afterwards, or you skip the next entity (which is re-indexed) for evaluation.
Also of note regarding your code, I see you are trying to make a copy of your list, but standard assignment means test and e both point to the same instance. You need to use Collections.copy() see this SO thread on how to use the class.
My requirement is to enter strings into an array which are not in the array. I also need to maintain fixed indexes, as this array will be used with other data structure with a one-to-one relation with each index. At present i am using the ArrayList class and checking with the indexOf () method to check if it exists first, if not then add it into the list with the add () method with one argument. I am not familiar to the classes in java, and therefore could not understand how can i implement it with HashMap or something else (trie or else), which will make the loading process fast .
Do the indexOf () in ArrayList makes a sequential search ?
My point is to reduce the processing time when loading the words into the array, with not inserting duplicates, and maintain fixed index of the elements. If a word tested is already in the array, then the index in which it is already inserted is required, as this index is needed to index into some other structure and do some processing. Any suggestions to make this process better?
UPDATE
There is an array, i have some documents from where i need to scan each word and find unique words in the documents. But also i need to count the number of duplicates. Stated in other way, i need to count the term frequencies of the unique terms occurring in the documents. I am maintaining a ArrayList<Integer[]> of term frequency (number of terms x number of docs). I am fetching one word and then checking if it is in the word list with the indexOf () method. If it is not present in the word list, then i am inserting the word into the list, and allocating a new row in the 2d array (the Array<Integer[]>) and then setting the count of the term element in 2d array to 1. If the word is already in the word array, then i use the index of the word in the array to index in the row of the Array<Integer[]> matrix, and use the current under processing document number to get to the cell and increment the count.
My question is to reduce the indexOf () processing time for each word i am currently using. I need to get the index of the word in the word array if it is already in there, and if it is not in there then i need to insert it into the array dynamically.
Sample Code
import java.io.*;
import java.util.ArrayList;
import static java.lang.Math.log;
class DocumentRepresentation
{
private String dirPath;
private ArrayList<String> fileNameVector;
private ArrayList<String> termVector;
private ArrayList<Integer[]> tf; /* store it in natural 2d array */
private Integer df[]; /* do normal 1d array */
private Double idf[]; /* do normal 1d array */
private Double tfIdf[][]; /* do normal 2d array */
DocumentRepresentation (String dirPath)
{
this.dirPath = dirPath;
fileNameVector = new ArrayList<String> ();
termVector = new ArrayList<String> ();
tf = new ArrayList<Integer[]> ();
}
/* Later sepatere the internal works */
public int start ()
{
/* Load the files, and populate the fileNameVector string */
File fileDir = new File (dirPath);
int fileCount = 0;
int index;
if (fileDir.isDirectory () == false)
{
return -1;
}
File fileList[] = fileDir.listFiles ();
for (int i=0; i<fileList.length; i++)
{
if (fileList[i].isFile () == true)
{
fileNameVector.add (fileList[i].getName ());
// System.out.print ("File Name " + (i + 1) + ": " + fileList[i].getName () + "\n");
}
}
fileCount = fileNameVector.size ();
for (int i=0;i<fileNameVector.size (); i++)
{
System.out.print ("Name " + (i+1) + ": " + fileNameVector.get (i) + "\n");
}
/* Bind the files with a buffered reader */
BufferedReader fileReaderVector[] = new BufferedReader [fileCount];
for (int i=0; i<fileCount; i++)
{
try
{
fileReaderVector[i] = new BufferedReader (new FileReader (fileList[i]));
}
/* Not handled */
catch (FileNotFoundException e)
{
System.out.println (e);
}
}
/* Scan the term frequencies in the tf 2d array */
for (int i=0; i<fileCount; i++)
{
String line;
try
{
/*** THIS IS THE PLACE OF MY QUESTION **/
while ((line = fileReaderVector[i].readLine ()) != null)
{
String words[] = line.split ("[\\W]");
for (int j=0;j<words.length;j++)
{
if ((index = termVector.indexOf (words[j])) != -1)
{
tf.get (index)[i]++;
/* increase the tf count */
}
else
{
termVector.add (words[j]);
Integer temp[] = new Integer [fileCount];
for (int k=0; k<fileCount; k++)
{
temp[k] = new Integer (0);
}
temp[i] = 1;
tf.add (temp);
index = termVector.indexOf (words[j]);
}
System.out.println (words[j]);
}
}
}
/* Not handled */
catch (IOException e)
{
System.out.println (e);
}
}
return 0;
}
}
class DocumentRepresentationTest
{
public static void main (String args[])
{
DocumentRepresentation docSet = new DocumentRepresentation (args[0]);
docSet.start ();
System.out.print ("\n");
}
}
Note: code is snipped to keep the focus on the question
LinkedHashMap can satisfy all your requirements at once, with good performance characteristics.
The keys would be your items and the values would be the indices. If you insert the elements in the order of increasing indices, then iterating over the map would also return the elements in the order of increasing indices.
Here is some sample code:
LinkedHashMap<Item,Integer> map = new LinkedHashMap<Item,Integer>();
Get the item's index:
Integer index = map.get(item);
if (index != null) {
// already in the map; use `index'
} else {
// not in the map
}
Add item with the next index:
if (!map.containsKey(item)) {
map.put(item, map.size());
}
Iterate over the elements in the order of increasing indices:
for (Entry<Item,Integer> e : map.entrySet()) {
Item item = e.getKey();
int index = e.getValue();
...
}
What this can't do efficiently is get the value at the specific index, but my reading of your question indicates that you don't actually need this.
ArrayList.indexOf() does a linear search, so it's O(n).
If it really has to go into an ArrayList, you could create two collections, ArrayList and HashSet. Add and remove elements to both collections. Before adding, call HashSet.contains() to see if the element already exists.
Encapsulate your ArrayList and HashSet in its own class.
If you want to leave the ArrayList you can have an HashSet as support, with the cost of the double of the memory.
You can use HashSet.add() if return true you can add also the element to the ArrayList
I am having trouble starting out this program. I am supposed to write a program that will populate an ArrayList by asking the user for 10 numbers.
After the list is made I'm to navigate it and if a number is even number, remove it from the ArrayList and put the number to a Stack of integers. So far I have this but I am confused on how to get the stack started so that I can put the even numbers into it:
import java.io.* ;
import java.util.*;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
ArrayList<Integer> test = new ArrayList<Integer>();
Stack<Integer> myStack = new Stack<Integer>();
System.out.print ("Enter Number: \n");
for (int i = 0; i < 10; i++) { //Put Into ArrayList
test.add(input.nextInt());
}
System.out.print("Contents of Array: " + test );
System.out.print("\n");
for (int i= 0; i < 10 ; i++) {
int item = myIterator.getNext();
if (item % 2 == 0) {
myListIterator.remove(); //removes it from the ArrayList
myStack.push(item); //puts it into the stack
}
}
System.out.print("Contents of Array afer numbers removed: " + test );
System.out.print("\n");
}
}
It seems that you just need to initialize the stack. Do the initialization of the stack where you initialize the test array.
Put this:
Stack<Integer> item = new Stack <Integer> ();
After:
ArrayList<Integer> test = new ArrayList<Integer>();
EDIT -- I was feeling generous, so I finished it for ya ;) You were actually almost all the way there, so I don't feel I really deprived you of a learning opportunity. The only other real thing you were missing was initializing the iterator and using it correctly.
Note the following:
-- you will see that if you use the iterator, you can just get rid of the for loop.
-- I changed the names of the variables so they are a bit easier to follow-naming is important.
-- Finally, since an ArrayList ISA List, you will notice I changed the declaration for the input values to use the interface for the declaration.
import java.util.*;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
List<Integer> inputValues = new ArrayList<Integer>();
Stack<Integer> evens = new Stack <Integer> ();
System.out.print("Enter Number: \n");
for (int i = 0; i < 10; i++) { //Put Into ArrayList
inputValues.add(input.nextInt());
}
System.out.println("Contents of Array: " + inputValues);
Iterator<Integer> iter = inputValues.iterator();
while(iter.hasNext()) {
Integer currentVal = iter.next();
if (currentVal % 2 == 0) {
iter.remove(); //removes it from the ArrayList
evens.push(currentVal); //puts it into the stack
} else {
System.out.println("No");
}
}
System.out.println("List values " + inputValues);
System.out.println("Stack values " + evens);
}
}
Hint: The commented out code has a declaration and initialization of a stack that is suitable for your purposes. It needs to be before the code that pushes stuff onto the stack.
I really doubt your code compiles without modification. For example myListIterator and myStack aren't even declared and I don't remember java Iterators to have a getNext() method.
Before using a variable, you must first declare it and the initialize it, these operations can be both done in one line, for example : Stack<Integer> myStack = new Stack<Integer>();
Looking at the tags of your question, this seems to be some kind of homework, I'm sure the documentation explains all of theses steps.
And since your using a ListIterator to remove the Integer from the ArrayList, there's no need to use a for loop, you can do something like
while(myListIterator.hasNext()) {
Integer item = myListIterator.next();
if(item % 2 == 0) {
item.remove();
myStack.add(item);
}
}