Java ArrayList<String> .contains() in hadoop - java

I am trying to remove the duplicated strings in an ArrayList called outputList in Hadoop.
Here is my code:
List<String> newList = new ArrayList<String>();
for( String item : outputList){
if(!newList.contains(item))
newList.add(item);
else newList.add("wrong");
}
The problems is that the strings in newList are all "wrong".
Some facts:
1. The above code works well at local machine.
I can write out the strings in outputList in hadoop. Most strings in outputList are different (duplicates exist).
I tried some other method to remove duplicated items. Like using HashSet. But when I use outputList to initialize a HashSet, the obtained HashSet is empty.
The java version in Hadoop is javac 1.6.0_18
Thanks.
The following is my reducer code:
public static class EditReducer
extends Reducer<Text,Text,Text,Text> {
private Text editor2 = new Text();
public void reduce(Text key, Iterable<Text> values,
Context context
) throws IOException, InterruptedException {
//write the content of iterable to an array list.
List<String> editorList =new ArrayList<String>();
for (Text t:values) {
editorList.add(t.toString());
}
//if a user appears more than once in the list, add to outputList
int occ;
List<String> outputList =new ArrayList<String>();
for (int i=0;i<editorList.size();i++) {
occ= Collections.frequency(editorList, editorList.get(i));
if(occ>1) {
outputList.add(editorList.get(i));
}
}
//make outputList distinct
List<String> newList = new ArrayList<String>();
for( String item : outputList){
if(!newList.contains(item))
newList.add(item);
else newList.add("wrong");
}
for (String val : newList) {
editor2.set(val);
context.write(editor2,editor2);
}
}
}

You can create a nested for loop inside your original for loop and compare the strings that way:
List<String> newList = new ArrayList<String>();
for(String item : outputList) {
boolean contains = false;
for(String str: newList) {
if(str.equals(item)) {
contains = true;
break;
}
}
if(!contains) {
newList.add(item);
}
else {
newList.add("wrong");
}
}

Related

How to replace a string starting with a letter in Java

I want to create a method that print out the elements in ArrayList.
If the String start with a, e, i, o or u, instead of printing the String, it should print Buzz.
I am trying this way. But it isn't work.
ArrayList<String> names = new ArrayList<>();
names.add("Harry");
names.add("Kathy");
ArrayList<String> replaceArray = new ArrayList<>();
String buzzReplace[] ={"a","e","i","o","u"};
for(String value:names)
{
if(value.startsWith(buzzReplace))
{
replaceArray = names.replaceAll(value,"Buzz");
}
System.out.println(replaceArray.get(value));
}
I found a simply solution :
for (String name: names) {
for (String vowel: buzzReplace) {
if (name.startsWith(vowel)) {
name = "buzz";
break;
}
}
System.out.println(name);
}
if(value.startsWith(buzzReplace))
If you think about the types involved here, clearly a string cannot start with an array of strings. A string can possibly start with another string.
So you need to iterate over the contents of your buzzReplace list:
for(String name : names)
{
for (String vowel : buzzReplace)
{
if (name.startsWith(vowel))
{
//do something
}
}
}
Your use of replaceAll is also incorrect and does not match the method signature. I'll leave it up to you to fix that element of your code. (a hint: you do not need to modify the contents of the list)
With Java 8 you could do something like this:
public List<String> buzz(List<String> names) {
List<Character> buzzChars = Arrays.asList('a', 'e', 'i', 'o', 'u');
return names.stream()
.map(name -> buzzChars.contains(name.toLowerCase().charAt(0)) ? "Buzz" : name)
.collect(Collectors.toList());
}
Instead of
if(value.startsWith(buzzReplace))
try
String[] buzzReplace ={"a","e","i","o","u"};
if (Arrays.asList(buzzRepalce).contains(value.subString(0,1))
This answer idea is like Jamesp's answer but as your code has some bugs and maybe you face them in next step, I send whole method.
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("Harry");
names.add("Kathy");
names.add("aathy");
ArrayList<String> replaceArray = new ArrayList<>();
String[] buzzReplace ={"a","e","i","o","u"};
for(String value:names)
{
if(Arrays.asList(buzzReplace).contains(value.substring(0,1)))
{
replaceArray.add("Buzz");
}
else replaceArray.add(value);
}
System.out.println(Arrays.toString(replaceArray.toArray()));
}
Write some method that does the task. let say. getReplacedList(List<String> names)
Now get the replaced array from that method.
private static List<String> getReplacedList(List<String> names) {
ArrayList<String> replaceArray = new ArrayList<>();
String buzzReplace = "aeiou";
names.stream().forEach(name ->{
//user to lower case if you want to ignore case.
if (buzzReplace.contains(name.toLowerCase().charAt(0)+"")) {
//do some thing like
replaceArray.add("Buzz");
} else {
replaceArray.add(name);
}
});
return replaceArray;
}
Now pass your original list to this method to get the replaced list.
Your solution look like.
public static void main(String... args) {
ArrayList<String> names = new ArrayList<>();
names.add("Harry");
names.add("Kathy");
List<String> replaceArray = new ArrayList<>();
replaceArray = getReplacedList(names);
//do some thing with replace array.
System.out.println(replaceArray.toString());
}
private static List<String> getReplacedList(List<String> names) {
ArrayList<String> replaceArray = new ArrayList<>();
String buzzReplace = "aeiou";
names.stream().forEach(name ->{
//user to lower case if you want to ignore case.
if (buzzReplace.contains(name.toLowerCase().charAt(0)+"")) {
//do some thing like
replaceArray.add("Buzz");
} else {
replaceArray.add(name);
}
});
return replaceArray;
}

Why do I need to create an array many times?

This programm shuffles a source list by pairs. So that original list
"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"
trasfoms to
11^12 19^20 17^18 15^16 1^2 5^6 3^4 13^14 7^8 9^10
The above is true while commented line is uncommented. Now, if line A is commented then all the elements in shuffleList are 19^20.
public class ShuffleService {
public static void shuffleList(List<String> list) {
System.out.println(list);
ArrayList<String[]> shuffleList = new ArrayList<String[]>(10);
String[] arr = new String[2];
boolean flag = false;
int step = 0;
for(String s: list){
if(flag){
arr[1]=s;
} else {
arr[0]=s;
}
flag=!flag;
step++;
if(step==2){
shuffleList.add(arr);
step=0;
//arr = new String[2]; //**line A**
}
}
Collections.shuffle(shuffleList);
for(String[] val: shuffleList){
System.out.print(val[0]);
System.out.print("^");
System.out.println(val[1]);
}
}
public static void main(String[] args) {
String[] a = new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"};
List<String> list1 = Arrays.asList(a);
shuffleList(list1);
}
}
So why do I need to uncomment line A in the program to work properly?
Because when you rewrite the values to arr (without remaking it), you're also going to modify the values already in the list.
Adding an object to the list doesn't stop you from modifying it, it will not make copies on its own. By calling new String[2] in your loop you're effectively building a new string array for each pair that you add to the list, which is what you want.

How to split a string into a map with a list of values?

I am a bit stuck with my application, and I am not quite sure what to search for. So I am hoping someone here may help me out.
I have a list of Strings, that looks like this:
Cake;carrot
Cake;apple
Cake;spicy
Pizza;pepperoni
Pizza;mozzarella
... and so on. I want to put this data into a Map<String, List<String>>, where Cake and Pizza will make up the keys in my Map. Having [carrot, apple, spicy] as Cake's values, and [pepperoni, mozzarella] as Pizza's values.
How may I achieve this? Thanks in advance for any help.
Just iterate over your list using String.split()
ArrayList<String> myList;
HashMap<String, List<String>> myMap = new HashMap<>();
for(String s : myList)
{
String[] split = s.split(";");
List<String> bucket = myMap.get(split[0]);
if(bucket == null)
{
bucket = new ArrayList<String>();
myMap.put(split[0], bucket);
}
bucket.add(split[1]);
}
You can try this, use a hashmap, store consecutive strings with (space) as the delimiter, finally split the string when you want it as a list
//Assuming your list to be the variable 'list'
HashMap<String,String> hm = new HashMap<>();
for(val : list){
String st[] = val.split(";");
if(hm.get(st[0])==null){
hm.put(st[0],st[1]);
}
else{
hm.put(st[0],hm.get(st[0])+" "+st[1]);
}
}
when You want the string array of say pizza back then
String pizz[] = (hm.get("pizza")).split(" ");
pizz[] will have your array, cheers!
public static void main(String[] args) {
List<String> data = new ArrayList<String>();
Map<String, List<String>> finalData = new HashMap<String,List<String>>();
data.add("Cake;carrot");
data.add("Cake;apple");
data.add("Cake;spicy");
data.add("Pizza;pepperoni");
data.add("Pizza;mozzarella");
for (String dataString : data) {
List<String> temp = null;
if (finalData.get(dataString.split(";")[0]) == null) {
temp = new ArrayList<String>();
temp.add(dataString.split(";")[1]);
finalData.put(dataString.split(";")[0], temp);
} else {
temp = finalData.get(dataString.split(";")[0]);
temp.add(dataString.split(";")[1]);
finalData.put(dataString.split(";")[0], temp);
}
}
System.out.println(new Gson().toJson(finalData));
}
Complete working solution.

Deleting elements from list using another list

I am trying to delete the elements from list1 that are in list1
package listCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Arry2List {
public static void main(String[] args) {
String[] s = {"INDIA" ,"JAPAN","THAILAND","MALAYSIA"};
ArrayList<String> list1= new ArrayList<String>();
String[] s1 = {"THAILAND","MALAYSIA"};
ArrayList<String> list2= new ArrayList<String>();
for(String temp : s)
{
list1.add(temp);
}
for(String temp : s1)
{
list2.add(temp);
}
//removing elements from list1 that are in list2
System.out.println("In list1 **************");
for (String t : list1)
{
System.out.println(t);
}
System.out.println("In list2 **************");
for (String t1 : list2)
{
System.out.println(t1);
}
//editlist(list1,list2);
Iterator<String> i=list1.iterator();
while( i.hasNext() )
{
if ( list2.contains( i.hasNext() ) )
{
i.remove();
}
}
System.out.println("In list1 again **************");
for(int i1 =0;i1<list1.size();i1++)
{
System.out.println(list1.get(i1));
}
}
}
Output should be INDIA,JAPAN.
List1 should contain only those elements which are not in the list2.
I am a beginner to Core Java and trying to learn collections.
In the loop that checks the element using List.contains(), you're passing a boolean (i.hasNext() returns whether the iterator has more elements) instead of the element. This causes the loop to run infinitely because you never call Iterator.next() to get the next element. You should use:
if (list2.contains(i.next())) {
instead of
if (list2.contains(i.hasNext())) {
It's better practice to also save the next element in a variable for re-usability:
while (i.hasNext()) {
String element = i.next();
if (list2.contains(element)) {
i.remove();
}
}
There is a built-in method to do that:
list1.removeAll(list2)
[EDIT]
You can create the lists easier using Arrays.asList:
List<String> list1 = new ArrayList<String>(Arrays.asList("INDIA", "JAPAN", "THAILAND", "MALAYSIA"));
List<String> list2 = Arrays.asList("THAILAND", "MALAYSIA");
list1.removeAll(list2);
[EDIT2]
The Arrays.asList produces unmodifiable list, so we have to use it to initialize a modifiable one.
[EDIT3]
Your code doesn't work because you don't advance the iterator. i.hasNext() only checks if there is a next element. It returns true or false, not the element itself. Here is how to fix this:
while (i.hasNext()) {
if (list2.contains(i.next())) {
i.remove();
}
}
You can also iterate over the list2 elements and remove them from list1:
for (String el : list2) {
list1.remove(el);
}

split an array list into multiple lists in java

I have an array list which when populated has a key and a value I want to know if there is a way of splitting it on repeating keys for example my current data is like this:
[RoleID_123.0, UserHandel_tom, Password_12345.0, prevPassword_null, userCaption_thomas, Email_tom#tom.tom, RoleID_124.0, UserHandel_dave, Password_ghadf, prevPassword_sdfsd, userCaption_david, Email_dave#dave.dave, RoleID_125.0, UserHandel_trevor, Password_tre, prevPassword_null, userCaption_trev, Email_trev#trev.trev]
I want it to come out more like this:
[RoleID_123.0, UserHandel_tom, Password_12345.0, prevPassword_null, userCaption_thomas, Email_tom#tom.tom]
[RoleID_124.0, UserHandel_dave, Password_ghadf, prevPassword_sdfsd, userCaption_david, Email_dave#dave.dave]
[RoleID_125.0, UserHandel_trevor, Password_tre, prevPassword_null, userCaption_trev, Email_trev#trev.trev]
Is there a way to split it on say role id or am I going about this the wrong way?
You can try by using HashMap
private static class MyItemHashMap extends HashMap {
public Item add(Item item) {
get(item).add(item);
return item;
}
public List get(Item key) {
List list = (List) get(createItemKey((Item) key));
return list == null ? createItemEntry((Item) key) : list;
}
private List createItemEntry(Item item) {
List list = new ArrayList();
put(createItemKey(item), list);
return list;
}
private Object createItemKey(Item item) {
return item.getSplitterProperty();
}
}
public static void main(String[] args) {
MyItemHashMap itemMapped = new MyItemHashMap();
List items = Arrays.asList(new Object[]{new Item("A"), new Item("B"),
new Item("C")});
for (Iterator iter = items.iterator(); iter.hasNext();) {
Item item = (Item) iter.next();
itemMapped.add(item);
}
}
If it is an ArrayList, there is no built-in function to split data like this; you will have to do it manually. If you know the number of consecutive fields that make a single structure, this shouldn't be too hard; something like this:
// 6 because there are 6 fields
for (int i = 0; i < arrayList.size(); i = i + 6) {
List thisList = arrayList.subList(i, i + 5);
// ... Now do whatever you want with thisList - it contains one structure.
}
If the number of fields can change then you'll have to do something a little more dynamic and loop through looking for a RoleID field, for example.
I'd use a HashMap to seperate the data instead of one long ArrayList ( you shouldn't have stored the data like this in the first instance )
HashMap<String,ArrayList<String>> hm = new HashMap<String,ArrayList<String>>;
// For each list:
ArrayList<String> arr = new ArrayList<String>;
arr.add("each element");
hm.put("RoleID_123.0", arr);
This way you will end up with a three dimensional structure with a key ( "RoleID..." ) pointing to its child elements.
Try this
String[] str=new String[]{"RoleID_123.0", "UserHandel_tom", "Password_12345.0", "prevPassword_null", "userCaption_thomas", "Email_tom#tom.tom", "RoleID_124.0", "UserHandel_dave", "Password_ghadf", "prevPassword_sdfsd", "userCaption_david", "Email_dave#dave.dave", "RoleID_125.0", "UserHandel_trevor", "Password_tre", "prevPassword_null", "userCaption_trev", "Email_trev#trev.trev"};
List<String> list=new ArrayList<>(Arrays.asList(str));
List<String> subList=list.subList(0,5);
You can try something similar to this
If you feel like taking a Linq-ee Libraried approach, this is about as good as it gets, and it requires use of a couple delegate objects:
import static com.google.common.collect.Collections2.filter;
import static com.google.common.collect.Collections2.transform;
//...
final List<String> yourList = //...
final int RECORD_LENGTH = 6;
Collection<String> roleIdValues = filter(yourList, new Predicate<String>() {
public boolean apply(#Nullable String input) {
return input != null && input.startsWith("RoleID");
}
});
Collection<Collection<String>> splitRecords = transform(roleIdValues, new Function<String, Collection<String>>() {
#Nullable public Collection<String> apply(#Nullable String input) {
return yourList.subList(yourList.indexOf(input), RECORD_LENGTH);
}
});
If Oracle had delivered Java 8 on time you would be able to do this in a way more slick manor. Ironically the reason you cant was provided by the same people providing the guava library

Categories

Resources