How to sort an arrayList using compareTo - java

As the user is inputting names, I want the names to sort out instantly using a compareTo method and return them in alphabetical order as the user is entering the names.
I've tried using a forLoop method but don't understand exactly how the compareTo method actually works, I've looked everywhere and can't find exactly how to complete it.
public class sortNames
{
public static void main(String[] args)
{
Scanner UI = new Scanner(System.in);
ArrayList<String> names = new ArrayList<String>();
System.out.println("Enter words, stop with -1");
while (true)
{
String input = UI.next();
if(!input.equals("-1"))
{
names.add(input);
System.out.println(names);
}
else
{
break;
}
}
}
}
I would want the output to look something like this
(User enters) "Bob"
(should return) [Bob]
(User enters) "Ally"
(should return) [Ally, Bob]
and so on with other names.

I think in your case you should choose TreeSet as the data structure to store the names in sorted order. Use :
TreeSet<String> names = new TreeSet<String>();
Instead of :
ArrayList<String> names = new ArrayList<String>();
Will solve your problem.

Just use ArrayList's method sort :
names.sort(null);
The null parameter indicates that the natural ordering (compareTo) should be used.

Related

Reduce loop function

I have my program working but I'm just want to reduce it. This is only a small part of my code. I created a list for each zipcode to be assigned to different people. I want to reduce it because I currently have more than 20 lists assigned to the same amount of loop.
public class zipcodes {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
List<Integer> pe1a = new ArrayList<>(Arrays.asList(1547,1549 ));
List<Integer> pe1b = new ArrayList<>(Arrays.asList(1606, 2458));
List<Integer> pe1c = new ArrayList<>(Arrays.asList(3058, 2214, 3895));
System.out.print("Enter the zipcode: ");
int zipCodeNumber = 0;
if (scnr.hasNextInt()) {
zipCodeNumber = scnr.nextInt();
} else {
System.out.println("Please enter a valid ZipCode:");
}
for (Integer list : pe1a) if (zipCodeNumber == list) System.out.println("John");
for (Integer list : pe1c) if (zipCodeNumber == list) System.out.println("Mark");
for (Integer list : pe1d) if (zipCodeNumber == list) System.out.println("Luna");
First at all I suggest to you to use a different data structure. Probably, I your case the best structure is an HashMap. The HashMap will allow you to have a single structure that hold all of your data.
var zipcodeMap = new HashMap<String, HashSet<Integer>>();
zipcodeMap.put("John", new HashSet<>(Arrays.asList(1547,1549)));
zipcodeMap.put("Mark", new HashSet<>(Arrays.asList(1606, 2458)));
zipcodeMap.put("Luna", new HashSet<>(Arrays.asList(3058, 2214, 3895)));
As you can see I put as a key of the HashMap a String object that hold the person name and as a value an HashSet that hold all the zip codes.
Now, that we have an HashMap we can easily replace all of these for-loops with a single forEach().
zipcodeMap.forEach((k, v) -> {
if (v.contains(zipCodeNumber)) {
System.out.println(k);
}
});
In practice, the forEach() go trough each key-value pair and check if the HashSet contains the zipCodeNumber. If the HashSet contains the zipCodeNumber print the key (that's the String object that hold the person name).

Simple words finder

We have to find all simple words from a bunch of simple and compound words. For example:
Input: chat, ever, snapchat, snap, salesperson, per, person, sales, son, whatsoever, what so.
Output should be: chat, ever, snap, per, sales, son, what, so
My sample code:
private static String[] find(String[] words) {
// TODO Auto-generated method stub
//System.out.println();
ArrayList<String> alist = new ArrayList<String>();
Set<String> r1 = new HashSet<String>();
for(String s: words){
alist.add(s);
}
Collections.sort(alist,new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
//System.out.println(alist.toString());
int count= 0;
for(int i=0;i<alist.size();i++){
String check = alist.get(i);
r1.add(check);
for(int j=i+1;j<alist.size();j++){
String temp = alist.get(j);
//System.out.println(check+" "+temp);
if(temp.contains(check) ){
alist.remove(temp);
}
}
}
System.out.println(r1.toString());
String res[] = new String[r1.size()];
for(String i:words){
if(r1.contains(i)){
res[count++] = i;
}
}
return res;
}
I am unable to get a solution with the above code. Any suggestions or ideas
compound word = concatenation of two or more words;rest all words are considered as simple words
We have to remove all the compound words
Algorithm
Read the input into a set of Strings i.e. Set<String> input
Create a empty set for simple words i.e. Set<String> simpleWords
Create a empty set for compound words i.e. Set<String> compoundWords
Iterate over input. For each element
Let length of element be elemLength
Create a set Set<String> inputs of all Strings from the set input (excluding element) for which the below is true
Length less than element
Not present in compundWords
Create set of all permutations of inputs(by concatenating) with max length = elemLength i.e. Set<String> currentPermutations
See if any of currentPermutations is = element
If yes, add element into compoundWords
If no, continue with iteration
After the iteration is done place all Strings from input which are not present in compoundWords into simpleWords
That is your answer.
Before you start writing code decide the logic that you are going to use. Use descriptive variable names and you are basically done.
The reason your logic is not working has to do with the way you are checking temp.contains(check). This is checking for substring not a compound word as per your definition.

Testing string and integer arrays against user input

I have created arrays for strings and integers I want to use in my program and I want to use them instead of using
(name.equals "barry"||"matty"
for example.
I want to know how to write the if statement to check the user input against the strings in the array.
import java.util.Scanner;
public class Username
{
public static void main (String[]args)
{
Scanner kb = new Scanner (System.in);
// array containing usernames
String [] name = {"barry", "matty", "olly","joey"};
System.out.println("Enter your name");
name = kb.nextLine();
if (name.equals("barry ")|| name.equals("matty" ) || name.equals("olly")||name.equals("joey"))
System.out.println("you are verified you may use the lift");
Scanner f = new Scanner(System.in);
int floor;
int [] floor = {0,1,2,3,4,5,6,7};
System.out.println("What floor do you want to go to ");
floor = f.nextInt();
if (floor >7)
System.out.println("Invalid entry");
else if (floor <= 7)
System.out.println("Entry valid");
}
}
I think you're just looking for List.contains - but that requires a List rather than an array, of course. There are two obvious options here.
Firstly, you could use a List<String> to start with:
List<String> names = new ArrayList<>();
names.add("barry");
names.add("matty");
names.add("olly");
names.add("joey");
...
if (names.contains(name))
{
...
}
Alternatively, you could use Arrays.asList to create a view:
String[] names = {"barry", "matty", "olly", "joey"};
List<String> namesList = Arrays.asList(names);
...
if (namesList.contains(name))
{
}
As a third option, if you put make your names array sorted (either by hand or by calling Arrays.sort) you could use Arrays.binarySearch to try to find the name entered by the user:
String[] names = {"barry", "matty", "olly", "joey"};
Arrays.sort(names);
...
if (Arrays.binarySearch(names, name) >= 0)
{
...
}
Arrays are very low-level structures that don't provide any method. You'd better use collections instead, which have a contains() method:
Set<String> names = new HashSet<>(Arrays.asList(new String[] {"barry", "matty", "olly","joey"}));
if (names.contains(name)) {
...
}
Since you don't seem to care about the order of the names, but only want to test if the collection contains a name or not, a HashSet is the best data structure: HashSet.contains() runs in constant time (O(1)), whereas List.contains(), for example, is O(n).
Read the collections tutorial.
You can loop through your array instead:
String name = kb.nextLine();
if(contains(name)) {
System.out.println("you are verified you may use the lift");
}
public boolean contains(String name) {
String [] names = {"barry", "matty", "olly","joey"};
for (int i = 0; i < names.length; i++) {
if(names[i].equals(name)) {
System.out.println("you are verified you may use the lift");
}
}
Or you can use List.contains(), in this case you have to add your names inside List instead of regular array.
For Example:
String[] names = {"barry", "matty", "olly", "joey"};
List<String> namesList= Arrays.asList(names);
if (namesList.contains(name)) {
System.out.println("you are verified you may use the lift");
}
Using ArrayList and List instead of Array of Strings:
List<String>names = new ArrayList<String>(names);
name = kb.nextLine();
if(names.indexOf(name)>-1)System.out.println("you are verified you may use the lift");
This because of the indexof in List returns -1 if not found or the index of the founded element, starting with 0.
I think that also
if(names.contains(name))System.out.println("you are verified you may use the lift");
works
Use a for loop
get input
for int i = 0, i < array size i++
if input.equals(array[i]) then do stuff
If you switch to an arraylist, you can do if(array.contains(input))

How to Count Unique Values in an ArrayList?

I have to count the number of unique words from a text document using Java. First I had to get rid of the punctuation in all of the words. I used the Scanner class to scan each word in the document and put in an String ArrayList.
So, the next step is where I'm having the problem! How do I create a method that can count the number of unique Strings in the array?
For example, if the array contains apple, bob, apple, jim, bob; the number of unique values in this array is 3.
public countWords() {
try {
Scanner scan = new Scanner(in);
while (scan.hasNext()) {
String words = scan.next();
if (words.contains(".")) {
words.replace(".", "");
}
if (words.contains("!")) {
words.replace("!", "");
}
if (words.contains(":")) {
words.replace(":", "");
}
if (words.contains(",")) {
words.replace(",", "");
}
if (words.contains("'")) {
words.replace("?", "");
}
if (words.contains("-")) {
words.replace("-", "");
}
if (words.contains("‘")) {
words.replace("‘", "");
}
wordStore.add(words.toLowerCase());
}
} catch (FileNotFoundException e) {
System.out.println("File Not Found");
}
System.out.println("The total number of words is: " + wordStore.size());
}
Are you allowed to use Set? If so, you HashSet may solve your problem. HashSet doesn't accept duplicates.
HashSet noDupSet = new HashSet();
noDupSet.add(yourString);
noDupSet.size();
size() method returns number of unique words.
If you have to really use ArrayList only, then one way to achieve may be,
1) Create a temp ArrayList
2) Iterate original list and retrieve element
3) If tempArrayList doesn't contain element, add element to tempArrayList
Starting from Java 8 you can use Stream:
After you add the elements in your ArrayList:
long n = wordStore.stream().distinct().count();
It converts your ArrayList to a stream and then it counts only the distinct elements.
I would advice to use HashSet. This automatically filters the duplicate when calling add method.
Although I believe a set is the easiest solution, you can still use your original solution and just add an if statement to check if value already exists in the list before you do your add.
if( !wordstore.contains( words.toLowerCase() )
wordStore.add(words.toLowerCase());
Then the number of words in your list is the total number of unique words (ie: wordStore.size() )
This general purpose solution takes advantage of the fact that the Set abstract data type does not allow duplicates. The Set.add() method is specifically useful in that it returns a boolean flag indicating the success of the 'add' operation. A HashMap is used to track the occurrence of each original element. This algorithm can be adapted for variations of this type of problem. This solution produces O(n) performance..
public static void main(String args[])
{
String[] strArray = {"abc", "def", "mno", "xyz", "pqr", "xyz", "def"};
System.out.printf("RAW: %s ; PROCESSED: %s \n",Arrays.toString(strArray), duplicates(strArray).toString());
}
public static HashMap<String, Integer> duplicates(String arr[])
{
HashSet<String> distinctKeySet = new HashSet<String>();
HashMap<String, Integer> keyCountMap = new HashMap<String, Integer>();
for(int i = 0; i < arr.length; i++)
{
if(distinctKeySet.add(arr[i]))
keyCountMap.put(arr[i], 1); // unique value or first occurrence
else
keyCountMap.put(arr[i], (Integer)(keyCountMap.get(arr[i])) + 1);
}
return keyCountMap;
}
RESULTS:
RAW: [abc, def, mno, xyz, pqr, xyz, def] ; PROCESSED: {pqr=1, abc=1, def=2, xyz=2, mno=1}
You can create a HashTable or HashMap as well. Keys would be your input strings and Value would be the number of times that string occurs in your input array. O(N) time and space.
Solution 2:
Sort the input list.
Similar strings would be next to each other.
Compare list(i) to list(i+1) and count the number of duplicates.
In shorthand way you can do it as follows...
ArrayList<String> duplicateList = new ArrayList<String>();
duplicateList.add("one");
duplicateList.add("two");
duplicateList.add("one");
duplicateList.add("three");
System.out.println(duplicateList); // prints [one, two, one, three]
HashSet<String> uniqueSet = new HashSet<String>();
uniqueSet.addAll(duplicateList);
System.out.println(uniqueSet); // prints [two, one, three]
duplicateList.clear();
System.out.println(duplicateList);// prints []
duplicateList.addAll(uniqueSet);
System.out.println(duplicateList);// prints [two, one, three]
public class UniqueinArrayList {
public static void main(String[] args) {
StringBuffer sb=new StringBuffer();
List al=new ArrayList();
al.add("Stack");
al.add("Stack");
al.add("over");
al.add("over");
al.add("flow");
al.add("flow");
System.out.println(al);
Set s=new LinkedHashSet(al);
System.out.println(s);
Iterator itr=s.iterator();
while(itr.hasNext()){
sb.append(itr.next()+" ");
}
System.out.println(sb.toString().trim());
}
}
3 distinct possible solutions:
Use HashSet as suggested above.
Create a temporary ArrayList and store only unique element like below:
public static int getUniqueElement(List<String> data) {
List<String> newList = new ArrayList<>();
for (String eachWord : data)
if (!newList.contains(eachWord))
newList.add(eachWord);
return newList.size();
}
Java 8 solution
long count = data.stream().distinct().count();

Find unique words in a file - Java

Using a msdos window I am piping in an amazon.txt file.
I am trying to use the collections framework. Keep in mind I want to keep this
as simple as possible.
What I want to do is count all the unique words in the file... with no duplicates.
This is what I have so far. Please be kind this is my first java project.
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Iterator;
public class project1 {
// ArrayList<String> a = new ArrayList<String>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String word;
String grab;
int count = 0;
ArrayList<String> a = new ArrayList<String>();
// Iterator<String> it = a.iterator();
System.out.println("Java project\n");
while (sc.hasNext()) {
word = sc.next();
a.add(word);
if (word.equals("---")) {
break;
}
}
Iterator<String> it = a.iterator();
while (it.hasNext()) {
grab = it.next();
if (grab.contains("a")) {
System.out.println(it.next()); // Just a check to see
count++;
}
}
System.out.println("I counted abc = ");
System.out.println(count);
System.out.println("\nbye...");
}
}
In your version, the wordlist a will contain all words but duplicates aswell. You can either
(a) check for every new word, if it is already included in the list (List#contains is the method you should call), or, the recommended solution
(b) replace ArrayList<String> with TreeSet<String>. This will eliminate duplicates automatically and store the words in alphabetical order
Edit
If you want to count the unique words, then do the same as above and the desired result is the collections size. So if you entered the sequence "a a b c ---", the result would be 3, as there are three unique words (a, b and c).
Instead of ArrayList<String>, use HashSet<String> (not sorted) or TreeSet<String> (sorted) if you don't need a count of how often each word occurs, Hashtable<String,Integer> (not sorted) or TreeMap<String,Integer> (sorted) if you do.
If there are words you don't want, place those in a HashSet<String> and check that this doesn't contain the word your Scanner found before placing into your collection. If you only want dictionary words, put your dictionary in a HashSet<String> and check that it contains the word your Scanner found before placing into your collection.

Categories