Reduce loop function - java

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).

Related

arraylist of character arrays java

I originally have an arraylist of strings but I want to save it as an arraylist of those strings.toCharArray() instead. Is it possible to make an arraylist that stores char arrays? Here is how I tried to implement it.
String[] words = new String[]{"peter","month","tweet", "pete", "twee", "pet", "et"};
HashMap<Integer,ArrayList<Character[]>> ordered = new HashMap<>();
int length = 0;
int max = 0; //max Length of words left
for(String word: words){
if(ordered.containsKey(length) == false){ //if int length key doesnt exist yet
ordered.put(length, new ArrayList<Character[]>()); //put key in hashmap with value of arraylist with the one value
ordered.get(length).add(word.toCharArray());
}
}
Note that toCharArray() returns an array of primitives (char[]), and not an array of the boxing class (Character[] as you currently have). Additionally, you're only adding the given array to the map if the length of the array isn't in the map, which probably isn't the behavior you wanted (i.e., you should move the line ordered.get(length).add(word.toCharArray()); outside the if statement).
Also, note that Java 8's streams can do a lot of the heavy lifting for you:
String[] words = new String[]{"peter","month","tweet", "pete", "twee", "pet", "et"};
Map<Integer, List<char[]>> ordered =
Arrays.stream(word)
.map(String::toCharArray)
.collect(Collectors.groupingBy(x -> x.length));
EDIT:
As per the question in the comment, this is also entirely possible in Java 7 without streams:
String[] words = new String[]{"peter","month","tweet", "pete", "twee", "pet", "et"};
Map<Integer, List<char[]>> ordered = new HashMap<>();
for (String word: words) {
int length = words.length();
// if int length key doesnt exist in the map already
List<char[]> list = orderd.get(length);
if (list == null) {
list = new ArrayList<>();
orderd.put(length, list);
}
list.add(word);
}

Getting Objects with specified values from hashtable Java

I have a hashtable with (String, Object). I have to segregate all objects by the length of the key String and create an array of arrays of Strings with the same length. Can someone guide me how could I accomplish that?
My code so far:
Set<String> keys = words.keySet();
ArrayList<ArrayList<Word>> outer = new ArrayList<ArrayList<Word>>();
ArrayList<Word> inner = new ArrayList<Word>();
for(String key: keys) {
for (int i=0; i< 15; i++) {
if (key.length() == i) {
inner.add(words.get(key));
}
outer.add(i, inner);
}
}
The way you're looping is inefficient since you may not have many words of certain sizes so you'll be needlessly checking the length of every single word against i for each length. You can just go through your list of words once and use a map to associate words with the keys representing their lengths, then collate the lists at the end.
Try this:
Map<Integer, List<String>> sizeMap = new HashMap<>();
for (String key: keys) {
int length = key.length();
if (sizeMap.containsKey(length)) {
// If we already have a list initialized, add the word
List<String> mWords = sizeMap.get(length);
mWords.add(key);
} else {
// Otherwise, add an empty list so later we don't try appending to null
sizeMap.put(length, new ArrayList<>());
}
}
// Convert the map to a list of lists
for (List<String> sizeGrouping : sizeMap.values()) {
outer.add(sizeGrouping);
}

Iterating through an array List and creating new ArrayLists when values are different, is this even possible?

I am fairly new to Java and I have stumbled across a problem I cannot figure out for the life of me. First let me explain what I am trying to do then I will show you the code I have so far.
I have a webservice that returns an array of arrays(which include company and lines of business strings). I wish to transform this into a string list, which I did in the first line of code below. Then I wish to Iterate through the list and every I come across a different value for company, I want to create a new ArrayList and add the associated line of business to the new list. Example output of webservice: 80,80,64,64 (this is presorted so the same companies will always be grouped together) the associated lobs would be 1,2,3,4 respectively. What I want: arraylist[0]: 1,2 arrayList[1]: 3,4
What I have so far:
List coList = Arrays.asList(coArray);
//create list of lists
List<List<String>> listOfLists = new ArrayList<List<String>>();
String cmp = "";
for (int i=0;i<coList.size();i++){//loop over coList and find diff in companies
String currentCo = ((__LOBList)coList.get(i)).getCompany();
String currentLob = ((__LOBList)coList.get(i)).getLobNum();
if(i<coArray.length-1){
String nextCo = ((__LOBList)coList.get(i+1)).getCompany();
if((currentCo.equals(nextCo))){
//do nothing companies are equal
}else{
log("NOT EQUAL"); //insert logic to create a new array??
ArrayList<String> newList = new ArrayList<String>();
// for(int j=0;j<coList.size();j++){
newList.add( ((__LOBList)coList.get(i)).getLobNum());
// }
for(int k=0; k<listOfLists.size();k++){//loop over all lists
for(int l=0;l<listOfLists.get(k).size();l++){ //get first list and loop through
}
listOfLists.add(newList);
}
}
}
}
My problem here is that it is not adding the elements to the new string array. It does correctly loop through coList and I put a log where the companies are not equal so I do know where I need to create a new arrayList but I cannot get it to work for the life of me, please help!
Yes you can do this but it's really annoying to write in Java. Note: This is a brain dead simple in a functional programming language like Clojure or Haskell. It's simply a function called group-by. In java, here's how I'd do this:
Initialize a List of Lists.
Create a last pointer that is a List. This holds the last list you've added to.
Iterate the raw data and populate into the last as long as "nothing's changed". If something has changed, create a new last.
I'll show you how:
package com.sandbox;
import java.util.ArrayList;
import java.util.List;
public class Sandbox {
public static void main(String[] args) {
ArrayList<String> rawInput = new ArrayList<String>();
rawInput.add("80");
rawInput.add("80");
rawInput.add("60");
rawInput.add("60");
new Sandbox().groupBy(rawInput);
}
public void groupBy(List<String> rawInput) {
List<List<String>> output = new ArrayList<>();
List<String> last = null;
for (String field : rawInput) {
if (last == null || !last.get(0).equals(field)) {
last = new ArrayList<String>();
last.add(field);
output.add(last);
} else {
last.add(field);
}
}
for (List<String> strings : output) {
System.out.println(strings);
}
}
}
This outputs:
[80, 80]
[60, 60]
Of course, you can do what the other guys are suggesting but this changes your data type. They're suggesting "the right tool for the job", but they're not mentioning guava's Multimap. This will make your life way easier if you decide to change your data type to a map.
Here's an example of how to use it from this article:
public class MutliMapTest {
public static void main(String... args) {
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
// Getting the size
int size = myMultimap.size();
System.out.println(size); // 4
// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
Collection<string> vegetables = myMultimap.get("Vegetables");
System.out.println(vegetables); // [Carrot]
// Iterating over entire Mutlimap
for(String value : myMultimap.values()) {
System.out.println(value);
}
// Removing a single value
myMultimap.remove("Fruits","Pear");
System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]
// Remove all values for a key
myMultimap.removeAll("Fruits");
System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
}
}
It sounds to me like a better choice would be a Map of Lists. Let the company ID be the key in the Map and append each new item for that company ID to the List that's the value.
Use the right tool for the job. Arrays are too low level.
Create a Map<String, List<Bussiness>>
Each time you retrieve a company name, first check if the key is already in the map. If it is, retrieve the list and add the Bussiness object to it. If it is not, insert the new value when a empty List and insert the value being evaluated.
try to use foreach instead of for
just like
foreach(List firstGroup in listOfLists)
foreach(String s in firstGroup)
............
Thanks for the input everyone!
I ended up going with a list of lists:
import java.util.*;
import search.LOBList;
public class arraySearch {
/**
* #param args
*/
public static void main(String[] args) {
LOBList test = new LOBList();
test.setCompany("80");
test.setLOB("106");
LOBList test1 = new LOBList();
test1.setCompany("80");
test1.setLOB("601");
LOBList test2 = new LOBList();
test2.setCompany("80");
test2.setLOB("602");
LOBList test3 = new LOBList();
test3.setCompany("90");
test3.setLOB("102");
LOBList test4 = new LOBList();
test4.setCompany("90");
test4.setLOB("102");
LOBList test5 = new LOBList();
test5.setCompany("100");
test5.setLOB("102");
LOBList BREAK = new LOBList();
BREAK.setCompany("BREAK");
BREAK.setLOB("BREAK");
BREAK.setcompany_lob("BREAK");
// create arraylist
ArrayList<LOBList> arlst=new ArrayList<LOBList>();
// populate the list
arlst.add(0,test);
arlst.add(1,test1);
arlst.add(2,test2);
arlst.add(3,test3);
arlst.add(4,test4);
arlst.add(5,test5);
//declare variables
int idx = 0;
String nextVal = "";
//loops through list returned from service, inserts 'BREAK' between different groups of companies
for(idx=0;idx<arlst.size();idx++){
String current = arlst.get(idx).getCompany();
if(idx != arlst.size()-1){
String next = arlst.get(idx+1).getCompany();
nextVal = next;
if(!(current.equals(next))){
arlst.add(idx+1,BREAK);
idx++;
}
}
}
//add last break at end of arrayList
arlst.add(arlst.size(),BREAK);
for(int i=0;i<arlst.size();i++){
System.out.println("co:" + arlst.get(i).getCompany());
}
//master array list
ArrayList<ArrayList<LOBList>> mymasterList=new ArrayList<ArrayList<LOBList>>();
mymasterList = searchListCreateNewLists(arlst);
//print log, prints all elements in all arrays
for(int i=0;i<mymasterList.size();i++){
for(int j=0;j<mymasterList.get(i).size();j++){
System.out.println("search method: " + mymasterList.get(i).get(j).getCompany());
}
System.out.println("end of current list");
}
}
//method to loop over company array, finds break, creates new array list for each company group,
//adds this to a list of lists(masterList)
public static ArrayList<ArrayList<LOBList>> searchListCreateNewLists(ArrayList<LOBList> list){
ArrayList<ArrayList<LOBList>> masterList=new ArrayList<ArrayList<LOBList>>();
int end = 0;
int start = 0;
int index = 0;
for(int i=0;i<list.size();i++){
if(list.get(i).getCompany().equals("BREAK")){
end = i;//end is current index
masterList.add(new ArrayList<LOBList>());
for(int j = start;j<end;j++){
masterList.get(index).add(list.get(j));
}
index++;
start = i+1;
}
}
return masterList;
}
}
The output is:
search method: 80
search method: 80
search method: 80
end of current list
search method: 90
search method: 90
end of current list
search method: 100
end of current list
So all company LOBList objects with Company: 80, are grouped together in a list, as are 90 and 100.
To iterate through the list you can use
ListIterator litr = coList.listIterator();
while(litr.hasNext()){
}

Duplicate elements in ArrayList

I have two array list, One is to save name and other is to save quantity. I want to avoid duplicate in the array list. Name array list contains name and its corresponding quantity is contained in quantity array list.
My array list can contains duplicate names, I want to traverse array list to check the name if already exists, if it exists then add the quantity to the previous value and delete duplicate entry.
Eg
Name Quantity
ABC 20
xyz 10
ABC 15
Output Required
Name Quantity
ABC 35
XYZ 10
Thanks
You should use a Map instead, which will not allow for duplicate entries. You use it something like this:
Map<String, Integer> nameToQuantityMap = new HashMap<String, Integer>():
nameToQuantityMap.put("Mr Smith", 100);
nameToQuantityMap.put("Mrs Jones", 500);
EDIT: Now that you've edited the question, the answer is different. If you want to add the values of duplicate keys, you'll have to do something like this:
// For each (name, quantity) pair
if (nameToQuantityMap.containsKey(name) ) {
Integer sum = nameToQuantityMap.get(name) + quantity;
nameToQuantityMap.put(name, sum);
}
else {
nameToQuantityMap.put(name, quantity);
}
I want to avoid duplicate in the array list.
In that case use HashSet
Or else if you have 2 parallel ArrayList then you can use HashMap
The structure you attempt to represent resembles something that should be represented by a Map, which is a key -> value storage type of structure. Having two lists and trying to keep the in sync is a bad idea.
Use java.util.Map where key would be you map and value would be value.
Map<String,Integer> map = new HashMap<>();
if(map.get(name)!=null){
Integer oValue = map.get(name)+nNalue;
}else
map.put(name,value);
Try this if you want to add value to the previous value if Key already exists .
public class Example {
static Map<String, Integer> map = new HashMap<String, Integer>();
public static void main(String[] args) {
insertNameAndQuantity("A", 10);
insertNameAndQuantity("B", 25);
insertNameAndQuantity("A", 25);
System.out.println(map);
}
public static void insertNameAndQuantity(String key, Integer value) {
Integer count = map.get(key);
if (count == null)
map.put(key, value);
else
map.put(key, count + value);
}
}
Output:
{A=35, B=25}
this is an example implement on c# code.
public class temp
{
[Test]
public void T()
{
var list1 = new ArrayList(){"ABC", "xyz", "ABC"};
var list2 = new ArrayList() {20, 10, 15};
var nameList = new List<string>();
var list1result = new ArrayList();
var list2result = new ArrayList();
int index = 0;
foreach (string name in list1)
{
if (!nameList.Contains(name))
{
list1result.Add(name);
var quantity = list2[index] ?? 0;
list2result.Add(quantity);
nameList.Add(name);
}
else
{
var index2 = 0;
foreach (string name2 in list1result)
{
if (name2 == name)
{
list2result[index2] = (int)list2result[index2] + (int)list2[index];
}
index2++;
}
}
index++;
}
Assert.True(list1result.Count == 2, list1result.Count + " t1");
}
}
I've tested the output, it's correct.

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();

Categories