How to remove duplicate elements in an array using HashMap without using hashset in java...Below code describes removal of duplicates in array..
Now i need to write using hashmap for generating key and value pairs
import java.util.*;
class TestArray{
public static void main(String arg[])
{
ArrayList<String> wordDulicate = new ArrayList<String>();
wordDulicate.add("chennai");
wordDulicate.add("bangalore");
wordDulicate.add("hyderabad");
wordDulicate.add("delhi");
wordDulicate.add("bangalore");
wordDulicate.add("mumbai");
wordDulicate.add("mumbai");
wordDulicate.add("goa");
wordDulicate.add("calcutta");
wordDulicate.add("hyderabad");
ArrayList<String> nonDupList = new ArrayList<String>();
Iterator<String> dupIter = wordDulicate.iterator();
while(dupIter.hasNext())
{
String dupWord = dupIter.next();
if(nonDupList.contains(dupWord))
{
dupIter.remove();
}else
{
nonDupList.add(dupWord);
}
}
System.out.println(nonDupList);
}
}
A HashSet is implemented in terms of a HashMap anyway. If you specifically want to use a HashMap, use it the same way as HashSet does: use a dummy constant new Object() as the map value everywhere.
Well a HashMap will prevent you from entering duplicate keys, the same way as HashSet. Actually, many implementations of HashSet just use a HashMap under the hood.
So you can do:
HashMap<String, String> map = new HashMap<String, String>();
for (String s : WordDuplicate)
map.put( s, s );
Now you can access the key/values just like a HashMap.
import java.util.HashSet;
import java.util.Stack;
public class stackdupes {
public static void main(String[] args) {
Stack<Integer> st = new Stack<Integer>();
int[] arr= {1,2,3,3,4,5,5,7};
HashSet<Integer> set = new HashSet<Integer>();
for (int i=0;i<arr.length;i++) {
if(set.add(arr[i]) == true)
st.push(arr[i]);
}
System.out.println(st);
}
}
Related
Let's say I have an array that takes instances of the type "Pessoal":
Pessoal[] teste = new Pessoal[6];
Now let's say I have 2 arraylists that are inside of an arraylist:
static ArrayList<Pessoal> lista_de_profs; // This one has 4
static ArrayList<Pessoal> lista_de_infos; // And this one has 2, matching the 6 on "teste"
// these arrayslists have instances of the type "Pessoal"
ArrayList<ArrayList<Pessoal>> lista_de_docentes = new ArrayList<>();
lista_de_docentes.add(lista_de_profs);
lista_de_docentes.add(lista_de_infos);
How do I iterate through the arraylist (lista_de_docentes) that contains more arraylists (lista_de_profs & lista_de_infos), and get their instances, so I can put them inside the array?
This works if teste's length is 4
for (int i = 0; i < teste.length; i++){
teste[i] = lista_de_profs.get(i);
}
But this only covers one arraylist, and I want all of the ones inside "lista_de_docentes", which are: "lista_de_profs" and "lista_de_infos"
*Some code in here, the language is in Portuguese, but I can change it to english, if it becomes confusing.
I hope I was clear, and thanks.
You can collect all your "Pessoal" elements into a single arraylist and then move the elements to your array
List<Pessoal> all= lista_de_docentes.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
for (int i =0; i < all.size(); i++)
teste[i] = all.get(i);
Or you can directly create the array (in case you don't care about the size)
Pessoal[] teste = lista_de_docentes.stream()
.flatMap(List::stream)
.collect(Collectors.toList())
.toArray(Pessoal[]::new);
You can do this with the stream API.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
public class Pessoal {
public static void main(String[] args) {
ArrayList<Pessoal> lista_de_profs = new ArrayList<>();
ArrayList<Pessoal> lista_de_infos = new ArrayList<>();
ArrayList<ArrayList<Pessoal>> lista_de_docentes = new ArrayList<>();
lista_de_docentes.add(lista_de_profs);
lista_de_docentes.add(lista_de_infos);
Pessoal[] teste = lista_de_docentes.stream()
.flatMap(l -> l.stream())
.collect(Collectors.toList())
.toArray(new Pessoal[0]);
System.out.println(Arrays.toString(teste));
}
}
lista_de_docentes.stream() creates a stream where every element has type ArrayList<Pessoal>.
flatMap returns a stream where every element has type Pessoal.
All the stream [Pessoal] elements are collected and put into a List.
Method toArray (of interface List) converts the List to an array.
Alternatively, if you don't want to use streams:
import java.util.ArrayList;
import java.util.Arrays;
public class Pessoal {
public static void main(String[] args) {
ArrayList<Pessoal> lista_de_profs = new ArrayList<>();
ArrayList<Pessoal> lista_de_infos = new ArrayList<>();
ArrayList<ArrayList<Pessoal>> lista_de_docentes = new ArrayList<>();
lista_de_docentes.add(lista_de_profs);
lista_de_docentes.add(lista_de_infos);
ArrayList<Pessoal> temp = new ArrayList<>();
for (ArrayList<Pessoal> list : lista_de_docentes) {
for (Pessoal p : list) {
temp.add(p);
}
}
Pessoal[] teste = new Pessoal[temp.size()];
temp.toArray(teste);
System.out.println(Arrays.toString(teste));
}
}
By the way, you should consider adopting Java naming conventions.
i have written a code which takes an array of integer and i am unable to figure out a way to remove the treemap elements which got (false) value.
Any help would be appreciated.
the code is as.
import java.util.*;
public class Solution {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
int x=s.nextInt();
String[] str=new String[x];
for(int i=0;i<x;i++)
{
str[i]=s.next();
}
TreeMap<Character, Boolean> store=new TreeMap<Character, Boolean>();
for(int i=0;i<str[0].length();i++)
{
store.put(str[0].charAt(i), false);
}
for(int i=1;i<str.length;i++)
{
for(int j=0;j<str[i].length();j++)
{
if(store.containsKey(str[i].charAt(j)))
{
store.put(str[i].charAt(i), true);
}
}
//code for removing elements from treemap with false value.
}
}
}
There is no efficient way to locate all the Map entries having a given value and removing them. You would have to iterate over all the entries in order to do that.
However, you don't have to do it. Just avoid putting them in the Map in the first place. Instead of putting the characters of the first String with false value in the Map, put them in a separate Set:
Map<Character, Boolean> store = new TreeMap<>();
Set<Character> set = new TreeSet<>();
for(int i=0;i<str[0].length();i++)
{
set.add(str[0].charAt(i));
}
for(int i=1;i<str.length;i++)
{
for(int j=0;j<str[i].length();j++)
{
if(set.contains(str[i].charAt(j)))
{
store.put(str[i].charAt(i), true);
}
}
}
If you have a TreeMap and you want to remove all false values, you can achieve that with a oneliner using lambdas in Java 8.
map.entrySet().removeIf(entry -> !entry.getValue()); // getValue() will return a boolean
I am trying to build a many to one key value pair in java. Till now all I have manged is this
public class KeyStore {
int i=1;
Map<Integer,String> map1=new HashMap<Integer,String>();
Map<String,List<Integer>> map2=new HashMap<String,List<Integer>>();
public synchronized int put(String blobString) {
if(map1.containsValue(blobString)){
int r=blobString.hashCode()+i*blobString.hashCode();
i++;
map1.put(r, blobString);
List<Integer> j=map2.get(blobString);
List<Integer> k=j;
map2.remove(blobString);
k.add(r);
map2.put(blobString, k);
return r;
}
else{
map1.put(blobString.hashCode(),blobString);
List<Integer> x=new ArrayList<Integer>();
x.add(blobString.hashCode());
map2.put(blobString,x);
return blobString.hashCode();
}
}
public synchronized String get(int objectId) {
return map1.get(objectId);
}
What this does is if i put
ks.put("abc")
ks.put("abc")
Here ks is an instant of the class containing the above methods.
it results in
{1916062554=abc, 958031277=abc}
But what I want is
191602554,958031277=abc
and if i use get() on either of these keys it should output the value abc. Also delete() should delete the most recent key and not harm the other keys.
I thought of using
Map<ArrayList<Integer>,String> keystore=new HashMap<ArrayListInteger>,String>();
but I dont know how to implement the put method i.e how to insert a key in a map of lists. Need help with this.
EDIT 1
I am able to make the get and put methods work. Struggling with the delete method. Wrote it some what like this
Map<Integer,String> map1=new HashMap<Integer,String>();
Map<String,List<Integer>> map2=new HashMap<String,List<Integer>>();
public synchronized void delete(int objectId) {
map1.remove(objectId);
Iterator<Entry<String, List<Integer>>> it = map2.entrySet().iterator();
loop1: while (it.hasNext()) {
#SuppressWarnings("rawtypes")
Map.Entry pairs = (Map.Entry)it.next();
#SuppressWarnings("unchecked")
List<Integer> z=(List<Integer>) pairs.getValue();
if(z.contains(objectId)){
//System.out.println(z.size());
String key=(String) pairs.getKey();
System.out.println(z+" "+key);
if(z.size()==1){
map2.remove(key);
break loop1;
}
else{
z.remove(objectId);
map2.remove(key);
map2.put(key, z);
break loop1;
}
}
}
}
Basically map1 contains the mappings
123=>abc,456=>abc
and map2 contains
abc=>[123,456]
I am getting an arrayindexoutofbound exception. What I am trying in the delete method is to iterate across each blob String and then check in the list of values associated with the blobstring whetehr the required objectID is present. if it is then I remove that object id from the list and append the new mapping. Any help?
EDIT 2
The updated and working get and put methods are given above.
The Map JavaDoc says:
A map cannot contain duplicate keys; each key can map to at most one value.
But you can get around this by making the value a list of strings:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
<P>{#code java MultiValueHashMap}</P>
**/
public class MultiValueHashMap {
public static final void main(String[] ignored) {
Map<Integer,List<String>> mapOfIntStrs = new HashMap<Integer,List<String>>();
//Add elements
addStringToMap(mapOfIntStrs, 1, "one");
addStringToMap(mapOfIntStrs, 1, "two");
addStringToMap(mapOfIntStrs, 1, "three");
addStringToMap(mapOfIntStrs, 2, "four");
addStringToMap(mapOfIntStrs, 2, "five");
//Output
Set<Integer> keyNumSet = mapOfIntStrs.keySet();
Iterator<Integer> keyNumItr = keyNumSet.iterator();
while(keyNumItr.hasNext()) {
Integer keyNum = keyNumItr.next();
List<String> strList = mapOfIntStrs.get(keyNum);
System.out.println(keyNum);
for(String s : strList) {
System.out.println(" " + s);
}
}
}
private static final void addStringToMap(Map<Integer,List<String>> mapTo_addTo, int keyNum, String value) {
if(mapTo_addTo.containsKey(keyNum)) {
mapTo_addTo.get(keyNum).add(value);
} else {
List<String> strList = new ArrayList<String>();
strList.add(value);
mapTo_addTo.put(keyNum, strList);
}
}
}
Output:
[C:\java_code\]java MultiValueHashMap
1
one
two
three
2
four
five
Regarding multiple keys per value, you could certainly do this, although I'm not sure it's recommended. According to the HashMap API:
The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.
And the Hashtable API:
To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.
So while this would work with ArrayList<Integer> keys, for anything with customized keys, containing non-standard classes, unless you are correctly implementing hashCode() for those objects, the HashMap may not function properly.
It seems like you need a couple of data structures as fields in your class:
stringMap: Map<Integer,String>
{1916062554=abc, 958031277=abc}, etc.
because for get you want to look up items by key
keys: Map<String,List<Integer>>
{ "abc" = {1916062554, 958031277}
because for delete you want to know the keys for a given item, in order.
To add to the Map:
public void put(String item) {
List<Integer> list = getOrCreateList(item,keys);
int key = calculateKey(item,list);
list.add(key);
stringMap.put(key,item);
}
private static List<Integer> getOrCreateList(String item, Map<String,List<Integer>> map) {
List<Integer> list = map.get(item);
if(list == null) {
list = new ArrayList<Integer>();
map.put(item,list);
}
return list;
}
To get from the map is easy:
public String get(int key) {
return stringMap.get(key);
}
To delete from the map -- if I understand your requirements correctly -- you need to find the most recent key in the list corresponding to the key provided...
public void delete(int key) {
String item = stringMap.get(key);
if(item == null) {
// ... deal with
}
List<Integer> keys = keys.get(item);
// lazily using methods which don't exist in the Java API
// but which illustrate the point.
keys.removeLast();
if(keys.isEmpty()) {
stringMap.remove(key);
list.remove(item);
}
}
I have this input:
5
it
your
reality
real
our
First line is number of strings comming after. And i should store it this way (pseudocode):
associative_array = [ 2 => ['it'], 3 => ['our'], 4 => ['real', 'your'], 7 => ['reality']]
As you can see the keys of associative array are the length of strings stored in inner array.
So how can i do this in java ? I came from php world, so if you will compare it with php, it will be very well.
MultiMap<Integer, String> m = new MultiHashMap<Integer, String>();
for(String item : originalCollection) {
m.put(item.length(), item);
}
djechlin already posted a better version, but here's a complete standalone example using just JDK classes:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String firstLine = reader.readLine();
int numOfRowsToFollow = Integer.parseInt(firstLine);
Map<Integer,Set<String>> stringsByLength = new HashMap<>(numOfRowsToFollow); //worst-case size
for (int i=0; i<numOfRowsToFollow; i++) {
String line = reader.readLine();
int length = line.length();
Set<String> alreadyUnderThatLength = stringsByLength.get(length); //int boxed to Integer
if (alreadyUnderThatLength==null) {
alreadyUnderThatLength = new HashSet<>();
stringsByLength.put(length, alreadyUnderThatLength);
}
alreadyUnderThatLength.add(line);
}
System.out.println("results: "+stringsByLength);
}
}
its output looks like this:
3
bob
bart
brett
results: {4=[bart], 5=[brett], 3=[bob]}
Java doesn't have associative arrays. But it does have Hashmaps, which mostly accomplishes the same goal. In your case, you can have multiple values for any given key. So what you could do is make each entry in the Hashmap an array or a collection of some kind. ArrayList is a likely choice. That is:
Hashmap<Integer,ArrayList<String>> words=new HashMap<Integer,ArrayList<String>>();
I'm not going to go through the code to read your list from a file or whatever, that's a different question. But just to give you the idea of how the structure would work, suppose we could hard-code the list. We could do it something like this:
ArrayList<String> set=new ArrayList<String)();
set.add("it");
words.put(Integer.valueOf(2), set);
set.clear();
set.add("your");
set.add("real");
words.put(Integer.valueOf(4), set);
Etc.
In practice, you probably would regularly be adding words to an existing set. I often do that like this:
void addWord(String word)
{
Integer key=Integer.valueOf(word.length());
ArrayList<String> set=words.get(key);
if (set==null)
{
set=new ArrayList<String>();
words.put(key,set);
}
// either way we now have a set
set.add(word);
}
Side note: I often see programmers end a block like this by putting "set" back into the Hashmap, i.e. "words.put(key,set)" at the end. This is unnecessary: it's already there. When you get "set" from the Hashmap, you're getting a reference, not a copy, so any updates you make are just "there", you don't have to put it back.
Disclaimer: This code is off the top of my head. No warranties expressed or implied. I haven't written any Java in a while so I may have syntax errors or wrong function names. :-)
As your key appears to be small integer, you could use a list of lists. In this case the simplest solution is to use a MultiMap like
Map<Integer, Set<String>> stringByLength = new LinkedHashMap<>();
for(String s: strings) {
Integer len = s.length();
Set<String> set = stringByLength.get(s);
if(set == null)
stringsByLength.put(len, set = new LinkedHashSet<>());
set.add(s);
}
private HashMap<Integer, List<String>> map = new HashMap<Integer, List<String>>();
void addStringToMap(String s) {
int length = s.length();
if (map.get(length) == null) {
map.put(length, new ArrayList<String>());
}
map.get(length).add(s);
}
I am piping in a file. I am tracking word pairs from the file. Using a treemap the keys are all sorted. However, when i add words to those keys they are not sorted.
here is the part i need help on in the process function:
private static void process(){
if(!result.containsKey(thisWord)){
result.put(thisWord, new ArrayList<String>());
}
// Add nextWord to the list of adjacent words to thisWord:
result.get(thisWord).add(nextWord); // nextword is not sorted within the key
thisword is sorted
nextWord is not..
Can i use Collections.sort(result); somehow?
im just not sure how i get to the nextWord within the result to do that.
or, is there no way to do it within my situation. I would rather not change things unless you recommend it.
This is the program
import java.util.Map.Entry;
import java.util.TreeSet;
import java.io.*;
import java.util.*;
public class program1 {
private static List<String> inputWords = new ArrayList<String>();
private static Map<String, List<String>> result = new TreeMap<String, List<String>>();
public static void main(String[] args) {
collectInput();
process();
generateOutput();
}
private static void collectInput(){
Scanner sc = new Scanner(System.in);
String word;
while (sc.hasNext()) { // is there another word?
word = sc.next(); // get next word
if (word.equals("---"))
{
break;
}
inputWords.add(word);
}
}
private static void process(){
// Iterate through every word in our input list
for(int i = 0; i < inputWords.size() - 1; i++){
// Create references to this word and next word:
String thisWord = inputWords.get(i);
String nextWord = inputWords.get(i+1);
// If this word is not in the result Map yet,
// then add it and create a new empy list for it.
if(!result.containsKey(thisWord)){
result.put(thisWord, new ArrayList<String>());
}
// Add nextWord to the list of adjacent words to thisWord:
result.get(thisWord).add(nextWord); // need to sort nextword
// Collections.sort(result);
}
}
private static void generateOutput()
{
for(Entry e : result.entrySet()){
System.out.println(e.getKey() + ":");
// Count the number of unique instances in the list:
Map<String, Integer> count = new HashMap<String, Integer>();
List<String> words = (List)e.getValue();
for(String s : words){
if(!count.containsKey(s)){
count.put(s, 1);
}
else{
count.put(s, count.get(s) + 1);
}
}
// Print the occurances of following symbols:
for(Entry f : count.entrySet()){
System.out.println(" " + f.getKey() + ", " + f.getValue() );
}
}
System.out.println();
}
}
If you want the collection of "nextword"s sorted, why not use a TreeSet rather than an ArrayList? The only reason I can see against it is if you might have duplicates. If duplicates are allowed, then yes, use Collections.sort on the ArrayList when you're done adding to them. Or look in the Apache Commons or Google collection classes - I don't know them off the top of my head, but I'm sure there is a sorted List that allows duplicates in one or both of them.
result.get(thisWord).add(nextWord);
Collections.sort(result.get(thisWord));
Y Don't you try some thing like this
Collections.sort(inputWords);