Java ilişkisel dizisi


214

PHP'deki gibi PHP'de ilişkilendirilebilir diziler nasıl oluşturabilir ve getirebilirim?

Örneğin:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';

Yanıtlar:


356

Java ilişkilendirilebilir dizileri desteklemez, ancak bu a kullanılarak kolayca gerçekleştirilebilir Map. Örneğin,

Map<String, String> map = new HashMap<String, String>();
map.put("name", "demo");
map.put("fname", "fdemo");
// etc

map.get("name"); // returns "demo"

Örneğinize göre daha da doğru (String'i ihtiyaçlarınızı karşılayan herhangi bir nesneyle değiştirebileceğiniz için) beyan etmek olacaktır:

List<Map<String, String>> data = new ArrayList<>();
data.add(0, map);
data.get(0).get("name"); 

Daha fazla bilgi için resmi belgelere bakın


2
Bu atacağım NullPointerExceptiondış haritası girişi için harita içermiyorsa 0. PHP $ arr [0] ['name'] ile daha izinli değil mi (bu dili hiç bilmiyorum)?
Tomasz Nurkiewicz

9
Var olmayan bir anahtara erişmeye çalışırsanız PHP hoşuna gitmez, hayır :)
Svish

2
@edem, bazı uygulamalar gerekliydi. Bugün ise ben tercih ediyorum ArrayListnedeniyle (beklenmeyen?) Performans farklılıkları neredeyse bütün davaları içinde. Ama bu başka bir tartışma.
Johan Sjöberg

3
Tam karma boyutunu başlatmayı ve yük faktörünü 1: HashMap <String, String> (kapasite, 1) olarak ayarlamayı asla unutmayın. Aksi takdirde büyük bir ek yük uygulayabilirsiniz ve nesnelerinizin çok fazla RAM'e ihtiyacı vardır. ArrayList için +1, ancak neden cevabın düzenlenmesi yok?
Marcus

1
@Marcus " Tam karma boyutunu başlatmayı ve yük faktörünü 1 olarak ayarlamayı asla unutmayın " - bu tavsiyeyi nereden alıyorsunuz? A'nın yük faktörünü neredeyse hiçbir zaman belirtmemelisiniz HashMapve kesinlikle davranışı kasıtlı olarak karşılaştırmadan ve kullanım durumunuz için daha iyi bir yük faktörü bulmadan kesinlikle belirtmemelisiniz. Başlangıç ​​boyutunu belirtmenin tek nedeni, haritanın çok büyük olacağını önceden bilmenizdir. HashMapboşsa (fazla) belleği boşa harcamaz, ancak büyük bir harita oluşturmak istiyorsanız, önündeki boyutu belirterek birkaç dizi yeniden boyut kaydedebilirsiniz.
dimo414

47

Java'nın PHP gibi ilişkilendirilebilir dizileri yoktur.

Yaptığınız şey için bir Harita kullanmak gibi çeşitli çözümler vardır, ancak bu bilgileri nasıl aramak istediğinize bağlıdır. Tüm bilgilerinizi tutan bir sınıfı kolayca yazabilir ve bunların örneklerini bir ArrayList.

public class Foo{
    public String name, fname;

    public Foo(String name, String fname){
        this.name = name;
        this.fname = fname;
    }
}

Ve sonra...

List<Foo> foos = new ArrayList<Foo>();
foos.add(new Foo("demo","fdemo"));
foos.add(new Foo("test","fname"));

Böylece onlara şu şekilde erişebilirsiniz ...

foos.get(0).name;
=> "demo"

20

Bunu Haritalar üzerinden yapabilirsiniz. Gibi bir şey

Map<String, String>[] arr = new HashMap<String, String>[2]();
arr[0].put("name", "demo");

Ancak Java'yı kullanmaya başladığınızda, verilerinizi temsil eden bir sınıf / model oluşturursanız en iyi seçeneklerin olacağını göreceksiniz. yapardım

class Person{
String name;
String fname;
}
List<Person> people = new ArrayList<Person>();
Person p = new Person();
p.name = "demo";
p.fname = "fdemo";
people.add(p);

Bu yöntemi daha çok sevdiğimi düşünüyorum. Her şeyin bu kadar basit olduğu php geliyor java kullanarak garip, ama harika bir çözüm. Teşekkürler.
Ayaz

ArrayList yerine List'i neden kullanmalıyım? burada bir Java acemi.
Sobiaholic

'Liste' soyut bir sınıftır ve 'ArrayList' bu sınıfın uygulamalarından biridir, aynı soyut sınıftan türetilen başka liste türleri de vardır. Bu nedenle bir ArrayList aynı zamanda bir Liste'dir. Soyut bir sınıfın örneğini oluşturamazsınız, sadece burada bir tür olarak kullanın, örnekleriniz için uygulamayı kullanmanız gerekir. Dolayısıyla Liste türdür ve ArrayList buradaki örnektir.
veta

12

Java'da ilişkilendirilebilir dizi diye bir şey yoktur. En yakın akrabası, Mapgüçlü bir şekilde yazılan a'dır, ancak daha az zarif sözdizimi / API'ye sahiptir.

Örneğinize göre alabileceğiniz en yakın şey budur:

Map<Integer, Map<String, String>> arr = 
    org.apache.commons.collections.map.LazyMap.decorate(
         new HashMap(), new InstantiateFactory(HashMap.class));

//$arr[0]['name'] = 'demo';
arr.get(0).put("name", "demo");

System.out.println(arr.get(0).get("name"));
System.out.println(arr.get(1).get("name"));    //yields null

1
Ne var LazyMap.decorateve InstantiateFactoryfalan mı?
Svish

+1 Diğer tüm cevaplar "anahtarlardan" birinin bir tamsayı olduğunu varsayar. İlişkilendirme dizisi tamsayı olmayan iki anahtara (python'da söyleyeceğimiz bir demet) dayalıysa? Endeksleme imkansız hale geldiğinden bu yaklaşımı kullanmanız gerektiğine inanıyorum.
demongolem

10

Bak Harita arayüzü ve beton sınıfı en HashMap .

Harita oluşturmak için:

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

Bir anahtar / değer çifti eklemek için:

assoc.put("name", "demo");

Bir anahtarla ilişkili değeri almak için:

assoc.get("name")

Elbette, istediğiniz gibi göründüğü için bir Haritalar dizisi oluşturabilirsiniz:

Map<String, String>[] assoc = ...

6

Peki ben de İlişkisel dizi arayışı içinde ve en iyi çözüm olarak harita listesi bulundu.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class testHashes {

public static void main(String args[]){
    Map<String,String> myMap1 = new HashMap<String, String>();

    List<Map<String , String>> myMap  = new ArrayList<Map<String,String>>();

    myMap1.put("URL", "Val0");
    myMap1.put("CRC", "Vla1");
    myMap1.put("SIZE", "Vla2");
    myMap1.put("PROGRESS", "Vla2");

    myMap.add(0,myMap1);
    myMap.add(1,myMap1);

    for (Map<String, String> map : myMap) {
        System.out.println(map.get("URL"));
    }

    //System.out.println(myMap);

}


}


5

Java'nın ilişkilendirilebilir dizileri yoktur, alabileceğiniz en yakın şey Harita arayüzüdür

İşte o sayfadan bir örnek.

import java.util.*;

public class Freq {
    public static void main(String[] args) {
        Map<String, Integer> m = new HashMap<String, Integer>();

        // Initialize frequency table from command line
        for (String a : args) {
            Integer freq = m.get(a);
            m.put(a, (freq == null) ? 1 : freq + 1);
        }

        System.out.println(m.size() + " distinct words:");
        System.out.println(m);
    }
}

Şununla çalıştırılırsa:

java Freq if it is to be it is up to me to delegate

Alacaksınız:

8 distinct words:
{to=3, delegate=1, be=1, it=2, up=1, if=1, me=1, is=2}

3

PHP'deki gibi PHP'deki ilişkisel diziler:

SlotMap hmap = new SlotHashMap();
String key = "k01";
String value = "123456";
// Add key value
hmap.put( key, value );

// check if key exists key value
if ( hmap.containsKey(key)) {
    //.....        
}

// loop over hmap
Set mapkeys =  hmap.keySet();
for ( Iterator iterator = mapkeys.iterator(); iterator.hasNext();) {
  String key = (String) iterator.next();
  String value = hmap.get(key);
}

Daha fazla bilgi için, bkz. Sınıf SoftHashMap: https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html


Map.containsKey () yöntemi, tüm Map anahtarlarında yinelenir ve anahtar bulunduğunda doğal olarak bir değer döndüren Map.get () yöntemi de yinelenir. Sadece Map.get () her iki tekniği de bu kodu yazmadan sadece bir kez (daha fazla performans) gerçekleştirir. Ayrıca Map.get (), eşleşen ilk anahtarla ilişkilendirilen değeri döndürür ve ardından aramayı durdurur, bu da daha hızlıdır ve bu model için tanıdık davranıştır. Bu yazıdaki kod, arama anahtarı eşleştikten sonra bile tüm anahtarlar arasında yinelenmeye devam eder ve son eşleşen anahtarı döndürür (ilk eşleşen anahtarı değil).
Matthew

3

ArrayList <Map <String, String>> kullanın

İşte bir kod örneği:

ArrayList<Map<String, String>> products = new ArrayList<Map<String, String>>();
while (iterator.hasNext()) {
         Map<String, String> product = new HashMap<String, String>();
         Element currentProduct = iterator.next();
         product.put("id",currentProduct.get("id"));
         product.put("name" , currentProduct.get("name") );
         products.add(product );
}
System.out.println("products : " + products);

Çıktı :

ürünler: [{id = 0001, ad = ürün1}, {id = 0002, ad = ürün2}]


1

JDK 1.5'te (http://tinyurl.com/3m2lxju) bir not bile vardır: "NOT: Bu sınıf kullanılmıyor. Bu uygulamayı genişletmek yerine yeni uygulamalar Harita arabirimini uygulamalıdır." Saygılarımızla, N.


1
Object[][] data = {
{"mykey1", "myval1"},
{"mykey2", "myval2"},
{new Date(), new Integer(1)},
};

Evet, bu değeri anahtar ile aramak için yineleme gerektirir, ancak hepsine ihtiyacınız varsa, bu en iyi seçim olacaktır.



0

Bunun hakkında daha fazla düşünerek, bu sorunu ele almanın daha genel amaçlı bir yolu olarak tuples atmak istiyorum. Tuples Java'ya özgü olmasa da, Javatuples'ı bana diğer dillerde var olacak aynı işlevselliği sağlamak için kullanıyorum . Sorulan soru ile nasıl başa çıkılacağına bir örnek şudur:

Map<Pair<Integer, String>, String> arr = new HashMap<Pair<Integer, String>, String>();
Pair p1 = new Pair(0, "name");
arr.put(p1, "demo");

Bu yaklaşımı seviyorum çünkü api sağlanan sınıflar ve yöntemler ile üçlü ve diğer yüksek sıralı gruplara genişletilebilir.


-2

PHP'nin 'Hayır, PHP hoşuna gitmedi' yorumu ile ilgili. Aslında, bazı çok kısıtlayıcı (PHP için) istisna / hata seviyeleri (ve belki de o zaman bile) ayarlamazsanız PHP çekmeye devam eder.

Varsayılan olarak OLACAK olan şey, varolmayan bir değişkene / sınırların dışında dizi öğesine erişimin, atadığınız değerinizi "kaldırması" dır. HAYIR, bu boş değil. PHP anladığım kadarıyla Perl / C soyuna sahiptir. Yani: ayarlanmamış ve mevcut olmayan değişkenler, ayarlanan değerler NULL, Boolean False değerleri, daha sonra standart dillerin sahip olduğu diğer her şey. Bunları ayrı ayrı test etmeniz veya VEYA işlev / sözdiziminde yerleşik SAĞ değerlendirmeyi seçmeniz gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.