completely new to Java, I am trying to find the matched element from one array into another, cannot seem to understand how to do it. Here is a sample of how the data is and how far I've gotten:
In this code and after printing this line, this is how the data is:
ArrayList<String> all_accounts = new ArrayList<String>();
all_accounts.add(acc);
System.out.println("\nArray 1:" + all_accounts);
Result Array 1:
Array 1:[77737320]
Array 1:[88405378]
Array 1:[00056893]
Array 1:[10709816]
ArrayList<String> cancel_accounts = new ArrayList<String>();
cancel_accounts.add(cancel_acc);
System.out.println("\nArray 2:" + cancel_accounts);
Results from Array 2:
Array 2:[77737320]
Array 2:[]
Array 2:[]
Array 2:[]
Stack here, I still cant understand why it doesn't match:
String found = null;
for (String account: all_accounts) {
for (String canceled: cancel_accounts) {
System.out.println(canceled);
found = canceled;
}
System.out.println(found);
if(account.equals(found) ) {
System.out.println(account);
}
}
I need to find the matched element, 77737320 in this case.
Thanks for looking!
+1 for answer from user6904265
However, You need not create a new HashSet. You can use ArrayList.retainAll(). If you want to maintain the all_accounts list, create a new clone and use that instead.
You could implement this as intersection between sets:
Set<String> set_all_account = new HashSet<String>(all_accounts);
Set<String> set_cancel_accounts = new HashSet<String>(cancel_accounts);
set_all_account.retainAll(set_cancel_accounts);
set_all_account.forEach(x -> System.out.println("Element matched: "+x));
Or as said by kartiks in his comment you could call the retainAll method directly on the all_accounts array:
all_accounts.retainAll(cancel_accounts);
all_accounts.forEach(x -> System.out.println("matched element: "+x));
Pay attention with this solution because in this case retainAll applies directly on the ArrayList and modifies it (as you can see the final result is in the all_accounts array). Moreover duplicate elements remain in the result array.
Last implementation (if you want compute intersection and print the result all in one line, also this version keeps duplicate elements):
all_accounts.stream().filter(x -> cancel_accounts.contains(x)).forEach(x -> System.out.println("matched element: "+x));
You can loop through the one list and search the second list for each element in first.
for (String account: all_accounts) {
if (cancel_accounts.contains(account) {
// Match found - do something....
System.out.println(account);
}
}
Just add an equals check to your for - loops (will work even without List#contains method)
for(String account: all_accounts) {
System.out.println(account);
for(String canceled: cancel_accounts){
System.out.println(canceled);
if(account.equals(cancelled)){
//you've found first intersection, cancelled exists in both
System.out.println(canceled + " is the same as " + account);
}
}
}
Related
I have one list which contains some String values. I want to iterate the list comparing with another String. Only if another String doesn't match with any element in the list, then I should enter the loop. I tried something like below, but it didn't worked. Any other alternate approach to do the same in Java 8?
Note: In the loop I'm adding some more elements to the same list. Hence, to avoid ConcurrentModificationException, I'm using a if-condition for my validation.
List<String> mylist = new ArrayList<>();
mylist.add("test");
mylist.add("test1");
if(mylist.stream()
.filter(str -> !(str.equalsIgnoreCase("test")))
.findFirst()
.isPresent()) {
System.out.println("Value is not Present");
}
You should be using Stream#noneMatch for this. It will make your code more readable and more concise. Also, try to avoid putting to much logic inside of your if statement, extract a max in readable variables
List<String> mylist = new ArrayList<>();
mylist.add("test");
mylist.add("test1");
Predicate<String> equalsIgnoreCasePredicate = str -> str.equalsIgnoreCase("test");
boolean noneMatchString = mylist.stream().noneMatch(equalsIgnoreCasePredicate);
if (noneMatchString) {
System.out.println("Value is not Present");
}
You should use noneMatch()
if (mylist.stream().noneMatch(str -> str.equalsIgnoreCase(testString))) {
System.out.println("Value is not Present");
}
The above can be achieved without using the Stream API. Below is a possible solution
String searchValue = "COW";
List<String> list = Arrays.asList("CAT", "DOG");
if(!list.contains(searchValue)){
System.out.println("Value is not Present");
}
Struggling with what is probably a simple query to match and return an element in an ArrayList.
I first store a HashSet in the ArrayList because HashSet has no get method and then check the ArrayList (which contains the correct elements, strings of socket references).
List theseSocks = new ArrayList(NodeConnMaster.sockList);
System.out.println("array list contains " + theseSocks);
I then want to iterate through and find the matching ipAddress in the element and once found set a variable to the entire element, so something like -
for (int i =0; i< theseSocks.size(); i++) {
if (theseSocks.toString().contains(ipAddress)) {
int element = theseSocks.get();
System.out.println("the element is " + element);
}
}
but it appears that get needs an index position and I am trying to get based on string contents, not index.
Is there an easier way than deleting all the elements except the matching one and then returning index 0.
Or is ArrayList not the way to go.
The solution was, with SBylemans's help -
Object currentSock = null;
for (int i =0; i< theseSocks.size(); i++)
{
currentSock = theseSocks.get(i);
if (currentSock.toString().contains(ipAddress))
{
System.out.println("the element is " +currentSock);
break;
}
}
Regards
Ralph
You can use stream of Java8 for filtering required elements like:
List wantedList = theseSocks.stream()
.filter(e ->e.toString().contains(ipAddress))
.collect(Collectors.toList())
You're looping over the ArrayList and want to compare based on the String value. But looping like this will immediately also give you the index. Your loop should look something like this:
for (int i =0; i< theseSocks.size(); i++)
{
String currentSock = theseSocks.get(i);
if (currentSock.equals(ipAddress))
{
System.out.println("the element is " +currentSock);
break;
}
}
Or even with a forEach loop
for (String currentSock: theseSocks)
{
if (currentSock.equals(ipAddress))
{
System.out.println("the element is " +currentSock);
break;
}
}
The break is used to interupt the for loop once your element is found.
Additionaly, your if condition will cause a print of every element if the array contains the ipAddress you're looking for.
Edit And then when using java 8, you can also use streams as posted by others.
I know this question has been answered on "how to find" many times, however I have a few additional questions. Here is the code I have
public static void main (String [] args){
List<String> l1= new ArrayList<String>();
l1.add("Apple");
l1.add("Orange");
l1.add("Apple");
l1.add("Milk");
//List<String> l2=new ArrayList<String>();
//HashSet is a good choice as it does not allow duplicates
HashSet<String> set = new HashSet<String>();
for( String e: l1){
//if(!(l2).add(e)) -- did not work
if(!(set).add(e)){
System.out.println(e);
}
Question 1:The list did not work because List allows Duplicate while HashSet does not- is that correct assumption?
Question 2: What does this line mean: if(!(set).add(e))
In the for loop we are checking if String e is in the list l1 and then what does this line validates if(!(set).add(e))
This code will print apple as output as it is the duplicate value.
Question 3: How can i have it print non Duplicate values, just Orange and Milk but not Apple? I tried this approach but it still prints Apple.
List unique= new ArrayList(new HashSet(l1));
Thanks in advance for your time.
1) Yes that is correct. We often use sets to remove duplicates.
2) The add method of HashSet returns false when the item is already in the set. That's why it is used to check whether the item exists in the set.
3) To do this, you need to count up the number of occurrances of each item in the array, store them in a hash map, then print out those items that has a count of 1. Or, you could just do this (which is a little dirty and is slower! However, this approach takes a little less space than using a hash map.)
List<String> l1= new ArrayList<>();
l1.add("Apple");
l1.add("Orange");
l1.add("Apple");
l1.add("Milk");
HashSet<String> set = new HashSet<>(l1);
for (String item : set) {
if (l1.stream().filter(x -> !x.equals(item)).count() == l1.size() - 1) {
System.out.println(item);
}
}
You're right.
Well... adding to the collection doesn't necessary need to return anything. Fortunately guys from the Sun or Oracle decided to return a message if the item was successfully added to the collection or not. This is indicated by true/false return value. true for a success.
You can extend your current code with the following logic: if element wasn't added successfully to the set, it means it was a duplicate so add it to another set Set<> duplicates and later remove all duplicates from the Set.
Question 1:The list did not work because List allows Duplicate while HashSet does not- is that correct assumption?
That is correct.
Question 2: What does this line mean: if(!(set).add(e)) In the for loop we are checking if String e is in the list l1 and then what does this line validates if(!(set).add(e))
This code will print apple as output as it is the duplicate value.
set.add(e) attempts to add an element to the set, and it returns a boolean indicating whether it was added. Negating the result will cause new elements to be ignored and duplicates to be printed. Note that if an element is present 3 times it will be printed twice, and so on.
Question 3: How can i have it print non Duplicate values, just Orange and Milk but not Apple? I tried this approach but it still prints Apple. List<String> unique= new ArrayList<String>(new HashSet<String>(l1));
There are a number of ways to approach it. This one doesn't have the best performance but it's pretty straightforward:
for (int i = 0; i < l1.size(); i++) {
boolean hasDup = false;
for (int j = 0; j < l1.size(); j++) {
if (i != j && l1.get(i).equals(l1.get(j))) {
hasDup = true;
break;
}
}
if (!hasDup) {
System.out.println(e);
}
}
With the /java8 power...
public static void main(String[] args) {
List<String> l1 = new ArrayList<>();
l1.add("Apple");
l1.add("Orange");
l1.add("Apple");
l1.add("Milk");
// remove duplicates
List<String> li = l1.parallelStream().distinct().collect(Collectors.toList());
System.out.println(li);
// map with duplicates frequency
Map<String, Long> countsList = l1.stream().collect(Collectors.groupingBy(fe -> fe, Collectors.counting()));
System.out.println(countsList);
// filter the map where only once
List<String> l2 = countsList.entrySet().stream().filter(map -> map.getValue().longValue() == 1)
.map(map -> map.getKey()).collect(Collectors.toList());
System.out.println(l2);
}
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();
I have an arrayList of arrayLists. Each inner arraylist contains some objects with the format (name.version) .
{ {a.1,b.2,c.3} , {a.2,d.1,e.1} , {b.3,f.1,z.1}....}
For example a.1 implies name = a and version is 1.
So i want to eliminate duplicates in this arraylist of lists. For me , two objects are duplicate when they have the same name
So essentially my output should be
{ { a.1,b.2,c.3},{d.1,e.1} ,{f.1 ,z.1} }
Note that i want the output in the exact same form (That is , i dont want a single list with no duplicates)
Can someone provide me with an optimal solution for this?
I can loop through each inner list and place the contents in the hashset. But two issues there, i cant get back the answer in
form of list of lists.Another issue is that when i need to override equals for that object , but i am not sure if that would
break other code. These objects are meaningfully equal if their names are same (only in this case. I am not sure that would
cover the entire spectrum)
Thanks
I used Iterator.remove() to modify the collection as you move through it.
// build your example input as ArrayList<ArrayList<String>>
String[][] tmp = { { "a.1", "b.2", "c.3" }, { "a.2", "d.1", "e.1" },
{ "b.3", "f.1", "z.1" } };
List<List<String>> test = new ArrayList<List<String>>();
for (String[] array : tmp) {
test.add(new ArrayList<String>(Arrays.asList(array)));
}
// keep track of elements we've already seen
Set<String> nameCache = new HashSet<String>();
// iterate and remove if seen before
for (List<String> list : test) {
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String element = it.next();
String name = element.split("\\.")[0];
if (nameCache.contains(name)) {
it.remove();
} else {
nameCache.add(name);
}
}
}
System.out.println(test);
Output
[[a.1, b.2, c.3], [d.1, e.1], [f.1, z.1]]
List<List<Pair>> inputs; // in whatever format you have them
List<List<Pair>> uniqued = new ArrayList<>(); // output to here
Set<String> seen = new HashSet<String>();
for (List<Pair> list : inputs) {
List<Pair> output = new ArrayList<>();
for (Pair p : list)
if (seen.add(p.getName()))
output.add(p);
uniqued.add(output);
}
Create a Set. Iterate over the list of lists' items. See if the item is in the Set. If it is already there, ignore it. If it isn't, add it to the Set and the list of lists.
Your method will return a new list of lists, not modify the old one. Modifying a list while iterating over it is a pain.