2015-06-09 8 views
0

У меня есть несколько многомерных экземпляров HashMap(), я использую их для хранения иерархических данных из базы данных;передать HashMap по ссылке

HashMap<String, HashMap<String, ArrayList<String>>> 

добавить к ним с 3-х основных методов, которые мы называем addTop(), addMid() и addLow(). Все методы принимают параметры, соответствующие их группе данных и строке, каждый метод возвращает следующее измерение HashMap();

public static HashMap<String, ArrayList<String>> addTop(HashMap<String, HashMap<String, ArrayList<String>>> data, String val) { ... }; 
public static ArrayList<String> addMid(HashMap<String, ArrayList<String>> data, String val) { ... }; 
public static String addLow(ArrayList<String> data, String val) { ... }; 

Я называю это, как правило, последовательно между несколькими проверками и выполнять дополнительные проверки внутри методов. По сути, все эти методы включают: val - data, затем возвращают пустой HashMap();

out = new HashMap(); 
data.put(val, out); 
return out; 

Когда я проверяю в конце цикла/данных многонаселенных всех данных из addMid() & addLow() отсутствует. Почему это?

Я думал, что Java работает по ссылке при работе со сложными объектами, такими как HashMap().

Что можно сделать для обеспечения того, чтобы addMid() и addLow() обновить мастер HashMap()?

EDIT: Включенный код. Он компилируется и запускается, но есть и другие проблемы. Я удалил столько, сколько мог, чтобы продемонстрировать, что происходит, за исключением SQL-материалов, которые не будут компилироваться, извините. метод, запускаемый при запуске, - sqlToArray();

import java.sql.SQLException; 
import java.util.ArrayList; 
import java.util.HashMap; 

public class Av2 { 
    protected class AvailLookup { 
     private Integer key; 
     private String value; 
     public AvailLookup(Integer inKey, String inValue) { 
      key = inKey; 
      value = inValue; 
     } 
     public void updateName(String name) { 
      value = name; 
     } 
     public Integer getKey() { 
      return key; 
     } 
     public String getValue() { 
      return value; 
     } 
     public String toString() { 
      return value; 
     } 
    } 
    private static HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>> data = new HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>>(); 
    private static Sql sql = new Sql("PlantAvail"); 
    public static HashMap<AvailLookup, ArrayList<AvailLookup>> getChannel(HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>> inArray, Integer channel) { 
     HashMap<AvailLookup, ArrayList<AvailLookup>> out = null; 
     if (inArray != null) { 
      for (AvailLookup lookup : inArray.keySet()) { 
       if (lookup.getKey() == channel) { 
        out = inArray.get(lookup); 
        System.out.println("Channel: " + channel + " found"); 
        break; 
       } 
      } 
      if (out == null) { 
       System.out.println("Channel: " + channel + " not found"); 
      } 
     } 
     return out; 
    } 
    public static HashMap<AvailLookup, ArrayList<AvailLookup>> getChannel(HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>> inArray, String channel) { 
     HashMap<AvailLookup, ArrayList<AvailLookup>> out = null; 
     if (inArray != null) { 
      for (AvailLookup lookup : inArray.keySet()) { 
       if (lookup.getValue() != null) { 
        if (lookup.getValue().equalsIgnoreCase(channel)) { 
         out = inArray.get(lookup); 
         System.out.println("Channel: " + channel + " found"); 
         break; 
        } 
       } 
      } 
      if (out == null) { 
       System.out.println("Channel: " + channel + " not found"); 
      } 
     } 
     return out; 
    } 
    public static HashMap<AvailLookup, ArrayList<AvailLookup>> addChannel(HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>> inArray, Integer id, String name) { 
     HashMap<AvailLookup, ArrayList<AvailLookup>> out = null; 
     if (inArray != null) { 
      if (getChannel(inArray, id) == null) { 
       out = new HashMap<AvailLookup, ArrayList<AvailLookup>>(); 
       inArray.put(new AvailLookup(id, name), new HashMap<AvailLookup, ArrayList<AvailLookup>>()); 
       System.out.println("Channel: added " + id); 
      } else { 
       System.out.println("Channel: " + id + " already exists"); 
      } 
     } else { 
      System.out.println("Channel: " + id + " already exists"); 
     } 
     return out; 
    } 
    public static void removeChannel(HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>> inArray, Integer channel) { 
     boolean pass = false; 
     HashMap<AvailLookup, ArrayList<AvailLookup>> channelLookup = getChannel(inArray, channel); 
     for (AvailLookup lookup : channelLookup.keySet()) { 
      if (lookup.getKey() == channel) { 
       inArray.remove(channel); 
       System.out.println("Channel: " + channel + " removed"); 
       pass = true; 
       break; 
      } 
     } 
     if (!pass) { 
      System.out.println("Channel: " + channel + " cannot be removed"); 
     } 
    } 
    public static ArrayList<AvailLookup> getDevice(HashMap<AvailLookup, ArrayList<AvailLookup>> channel, Integer device) { 
     ArrayList<AvailLookup> out = null; 
     for(AvailLookup lookup : channel.keySet()) { 
      if (lookup.getKey() == device) { 
       out = channel.get(device); 
       System.out.println("Device: " + device + " found"); 
       break; 
      } 
     } 
     if (out == null) { 
      System.out.println("Device: " + device + " not found"); 
     } 
     return out; 
    } 
    public static ArrayList<AvailLookup> getDevice(HashMap<AvailLookup, ArrayList<AvailLookup>> channel, String device) { 
     ArrayList<AvailLookup> out = null; 
     for(AvailLookup lookup : channel.keySet()) { 
      if (lookup.getValue() == device) { 
       out = channel.get(device); 
       System.out.println("Device: " + device + " found"); 
       break; 
      } 
     } 
     if (out == null) { 
      System.out.println("Device: " + device + " not found"); 
     } 
     return out; 
    } 
    public static ArrayList<AvailLookup> addDevice(HashMap<AvailLookup, ArrayList<AvailLookup>> channel, Integer id, String value) { 
     ArrayList<AvailLookup> out = null; 
     if (getDevice(channel, id) == null) { 
      out = new ArrayList<AvailLookup>(); 
      channel.put(new AvailLookup(id, value), new ArrayList<AvailLookup>()); 
      System.out.println("Device: added " + id); 
     } else { 
      System.out.println("Device: " + id + " already exists"); 
     } 
     return out; 
    } 
    public static void removeDevice(HashMap<AvailLookup, ArrayList<AvailLookup>> channel, Integer device) { 
     boolean pass = false; 
     ArrayList<AvailLookup> deviceLookup = getDevice(channel,device); 
     for (AvailLookup lookup : deviceLookup) { 
      if (lookup.getKey() == device) { 
       channel.remove(device); 
       System.out.println("Device: " + device + " removed"); 
       pass = true; 
       break; 
      } 
     } 
     if (!pass) { 
      System.out.println("Device: " + device + " cannot be removed"); 
     } 
    } 
    public static AvailLookup getHost(ArrayList<AvailLookup> hosts, Integer host) { 
     AvailLookup out = null; 
     for (AvailLookup hostLookup : hosts) { 
      if (hostLookup.getKey() == host) { 
       out = hostLookup; 
       System.out.println("Host: " + host + " found"); 
      } 
     } 
     if (hosts.contains(host)) { 
     } else { 
      System.out.println("Host: " + host + " not found"); 
     } 
     return out; 
    } 
    public static AvailLookup getHost(ArrayList<AvailLookup> hosts, String host) { 
     AvailLookup out = null; 
     for (AvailLookup hostLookup : hosts) { 
      if (hostLookup.getValue() == host) { 
       out = hostLookup; 
       System.out.println("Host: " + host + " found"); 
      } 
     } 
     if (hosts.contains(host)) { 
     } else { 
      System.out.println("Host: " + host + " not found"); 
     } 
     return out; 
    } 
    public static AvailLookup addHost(ArrayList<AvailLookup> hosts, Integer id, String value) { 
     AvailLookup out = null; 
     for (AvailLookup hostLookup : hosts) { 
      if (hostLookup.getKey() == id) { 
       out = hosts.set(id, new AvailLookup(id, value)); 
       System.out.println("Host: " + id + " found"); 
       break; 
      } 
     } 
     if (out == null) { 
      System.out.println("Host: " + id + " not found"); 
     } 
     return out; 
    } 
    public static void removeHost(ArrayList<AvailLookup> hosts, Integer host) { 
     boolean pass = false; 
     for (AvailLookup hostLookup : hosts) { 
      if (hostLookup.getKey() == host) { 
       hosts.remove(hostLookup); 
       System.out.println("Host: " + host + " removed"); 
       pass = true; 
      } 
     } 
     if (!pass) { 
      System.out.println("Host: " + host + " cannot be removed"); 
     } 
    } 
    public static ArrayList<AvailLookup> otherHosts(ArrayList<AvailLookup> hosts, Integer key, String value) { 
     ArrayList<AvailLookup> out = null; 
     for (AvailLookup host : hosts) { 
      if (host.getKey() != key) { 
       if (out == null) { 
        out = new ArrayList<AvailLookup>(); 
       } 
       out.add(new AvailLookup(key, value)); 
      } 
     } 
     if (out != null) { 
      if (out.size() > 1) { 
       System.out.println("Host: generated other hosts"); 
      } 
     } 
     return out; 
    } 
    public static AvailLookup nextHost(ArrayList<AvailLookup> otherHosts) { 
     AvailLookup out = null; 
     if (otherHosts != null) { 
      out = otherHosts.get(0); 
      System.out.println("Host: getting next host"); 
     } else { 
      System.out.println("Host: no other host"); 
     } 
     return out; 
    } 
    public static void sqlToArray() { 
     HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>> tempData = new HashMap<AvailLookup, HashMap<AvailLookup, ArrayList<AvailLookup>>>(); 
     Integer iHost = null; 
     Integer iDevice = null; 
     Integer iChannel = null; 
     String sHost = null; 
     String sDevice = null; 
     String sChannel = null; 
     HashMap<AvailLookup, ArrayList<AvailLookup>> channel = null; 
     ArrayList<AvailLookup> device = null; 
     Sql obj = new Sql("plantavail"); 
     obj.query("select j_channel.id as channelid, j_channel.name as channelname, j_device.id as deviceid, j_device.name as devicename, j_io.id as hostid, j_io.host as hostname, alias" 
       + " from j_io" 
       + " left join j_channel on j_io.id = j_channel.iofk" 
       + " left join j_device on j_channel.iofk = j_device.id"); 
     try { 
      while(obj.getResult().next()) { 
       sChannel = obj.getResult().getString("channelname"); 
       sDevice = obj.getResult().getString("devicename"); 
       sHost = obj.getResult().getString("hostname"); 
       iChannel = obj.getResult().getInt("channelid"); 
       iDevice = obj.getResult().getInt("deviceid"); 
       iHost = obj.getResult().getInt("hostid"); 
       channel = addChannel(tempData, iChannel, sChannel); 
       if (channel != null) { 
        device = addDevice(channel, iDevice, sDevice); 
        if (device != null) { 
         addHost(device, iHost, sHost); 
        } 
       } 
      } 
     } catch (SQLException e1) { 
      e1.printStackTrace(); 
     } 
     data = tempData; 
    } 
} 
+6

Показать цикл данных. Возможно, вы не проходите мимо того, что думаете, что проходите. И как эти методы могут возвращать 'out', если' out' является сырой 'HashMap', а их возвращаемое значение -' ArrayList (String) 'и' String'? Вы не показываете настоящий код, показываете реальный код или создаете [MCVE] (http://stackoverflow.com/help/mcve). – RealSkeptic

+1

Пример, который вы опубликовали, не пригодится. Напишите простой и представительный пример, который полностью работает ** и демонстрирует вашу проблему. –

+0

Java [всегда проходит по значению] (http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). Терминология просто сбивает с толку, потому что «пройти по ссылке» и «передавать ссылки» - это разные вещи. – Radiodef

ответ

1

Вам нужно проверить, если уже есть карта для этого ключа:

Map<...> result = data.get(val); 
if(null == result) { 
    result = new HashMap(); 
    data.put(val, result); 
} 
return out; 

Без этого, вторая попытка добавить значения в том же ключе перезаписывает существующую карту вместо добавления к нему.

2

Будьте осторожны при случайном переопределении существующих значений карты. Если вы используете Java 8 вы можете использовать:

map.computeIfAbsent("entry", s -> new ArrayList<>()); 

Перед Java 8 вам нужно проверить, если значение равно нулю:

List<String> list = map.get("entry"); 

if(list == null){ 
    list = map.put("entry", new ArrayList<String>()); 
} 

Кроме того, необходимо убедиться, что вы обновляете вашу карту правильно :

небольшой пример:

Map<String, String> map = new HashMap<>(); 

String a = "a"; 
String b = "b"; 

map.put(a, b); 

System.out.println(map.get(a)); 

b = "c"; 

System.out.println(map.get(a)); 
System.out.println(b); 

Выход:

b 
b 
c 

Итак, вы видите, обновляетесь ли вы, карта не обновляется. Теперь то же самое с картой в карте:

final String a = "a"; 
final String b = "b"; 

Map<String, Map<String, String>> topMap = new HashMap<>(); 
Map<String, String> middleMap = topMap.getOrDefault(a, new HashMap<>()); 

middleMap.put(b, "c"); 

topMap.put("a", middleMap); 

System.out.println(topMap.get(a).get(b)); 

middleMap.replace(b, "d"); 

System.out.println(topMap.get(a).get(b)); 

topMap.put("a", middleMap); 

System.out.println(topMap.get(a).get(b)); 

Выход есть:

c 
d 
d 

Но почему? Разве это не должно быть «c c d»? НЕТ! Поскольку String в Java неизменен, но Map нет. Если вы считаете это, вы должны решить свою проблему.

+0

См., Я думаю, я это рассмотрел. Но я не уверен, как поместить карту после создания, учитывая поток процесса. Кроме того, я не знаю, как переписать поток процесса для его поддержки. – psycotik

+0

Во-первых, и, что еще хуже, вы, например, имеете rawtypes здесь 'List list' и здесь' new ArrayList() '. Во-вторых, 'getOrDefault' будет ** всегда ** создавать' новый ArrayList' - это маловероятно, что вы хотите для всех. Вы хотите ['Map.computeIfAbsent'] (https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#computeIfAbsent-K-java.util.function.Function-) , –

+0

@BoristheSpider Секция перед Java 8 является просто примером, чтобы получить точку. В любом случае, я обновлю его. Ваше второе утверждение просто неверно. getOrDefault создаст только новый объект, если карта не содержит ключ. API Java 8 говорит: «Возвращает значение, на которое указан указанный ключ, или значение по умолчанию, если эта карта не содержит сопоставления для ключа». https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#getOrDefault-java.lang.Object-V- –

Смежные вопросы